blob: 746a5ae08f9ddae152eff7622de62c845c845065 [file] [log] [blame]
// Copyright 2014 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/shell/test_runner/mock_webrtc_peer_connection_handler.h"
#include <stddef.h>
#include <string>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/memory/ptr_util.h"
#include "content/shell/test_runner/mock_webrtc_data_channel_handler.h"
#include "content/shell/test_runner/mock_webrtc_dtmf_sender_handler.h"
#include "content/shell/test_runner/test_interfaces.h"
#include "content/shell/test_runner/web_test_delegate.h"
#include "third_party/WebKit/public/platform/WebMediaStream.h"
#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
#include "third_party/WebKit/public/platform/WebRTCAnswerOptions.h"
#include "third_party/WebKit/public/platform/WebRTCDataChannelInit.h"
#include "third_party/WebKit/public/platform/WebRTCOfferOptions.h"
#include "third_party/WebKit/public/platform/WebRTCPeerConnectionHandlerClient.h"
#include "third_party/WebKit/public/platform/WebRTCRtpContributingSource.h"
#include "third_party/WebKit/public/platform/WebRTCRtpReceiver.h"
#include "third_party/WebKit/public/platform/WebRTCRtpSender.h"
#include "third_party/WebKit/public/platform/WebRTCStatsResponse.h"
#include "third_party/WebKit/public/platform/WebRTCVoidRequest.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebVector.h"
using namespace blink;
namespace test_runner {
namespace {
uintptr_t GetIDByTrack(const std::string& track_id,
std::map<std::string, uintptr_t>* id_by_track) {
const auto& it = id_by_track->find(track_id);
if (it == id_by_track->end()) {
uintptr_t id = static_cast<uintptr_t>(id_by_track->size()) + 1;
id_by_track->insert(std::make_pair(track_id, id));
return id;
}
return it->second;
}
class MockWebRTCLegacyStats : public blink::WebRTCLegacyStats {
public:
class MemberIterator : public blink::WebRTCLegacyStatsMemberIterator {
public:
MemberIterator(
const std::vector<std::pair<std::string, std::string>>* values)
: values_(values) {}
// blink::WebRTCLegacyStatsMemberIterator
bool IsEnd() const override { return i >= values_->size(); }
void Next() override { ++i; }
blink::WebString GetName() const override {
return blink::WebString::FromUTF8((*values_)[i].first);
}
blink::WebRTCLegacyStatsMemberType GetType() const override {
return blink::kWebRTCLegacyStatsMemberTypeString;
}
int ValueInt() const override {
NOTREACHED();
return 0;
}
int64_t ValueInt64() const override {
NOTREACHED();
return 0;
}
float ValueFloat() const override {
NOTREACHED();
return 0.0f;
}
blink::WebString ValueString() const override {
return blink::WebString::FromUTF8((*values_)[i].second);
}
bool ValueBool() const override {
NOTREACHED();
return false;
}
blink::WebString ValueToString() const override { return ValueString(); }
private:
size_t i = 0;
const std::vector<std::pair<std::string, std::string>>* values_;
};
MockWebRTCLegacyStats(const char* id, const char* type_name, double timestamp)
: id_(id), type_name_(type_name), timestamp_(timestamp) {}
// blink::WebRTCLegacyStats
blink::WebString Id() const override {
return blink::WebString::FromUTF8(id_);
}
blink::WebString GetType() const override {
return blink::WebString::FromUTF8(type_name_);
}
double Timestamp() const override { return timestamp_; }
blink::WebRTCLegacyStatsMemberIterator* Iterator() const override {
return new MemberIterator(&values_);
}
void addStatistic(const std::string& name, const std::string& value) {
values_.push_back(std::make_pair(name, value));
}
private:
const std::string id_;
const std::string type_name_;
const double timestamp_;
// (name, value) pairs.
std::vector<std::pair<std::string, std::string>> values_;
};
template <typename T>
WebVector<T> sequenceWithValue(T value) {
return WebVector<T>(&value, 1);
}
class MockWebRTCStatsMember : public blink::WebRTCStatsMember {
public:
MockWebRTCStatsMember(const std::string& name,
blink::WebRTCStatsMemberType type)
: name_(name), type_(type) {}
// blink::WebRTCStatsMember overrides.
blink::WebString GetName() const override {
return blink::WebString::FromUTF8(name_);
}
blink::WebRTCStatsMemberType GetType() const override { return type_; }
bool IsDefined() const override { return true; }
bool ValueBool() const override { return true; }
int32_t ValueInt32() const override { return 42; }
uint32_t ValueUint32() const override { return 42; }
int64_t ValueInt64() const override { return 42; }
uint64_t ValueUint64() const override { return 42; }
double ValueDouble() const override { return 42.0; }
blink::WebString ValueString() const override {
return blink::WebString::FromUTF8("42");
}
WebVector<int> ValueSequenceBool() const override {
return sequenceWithValue<int>(1);
}
WebVector<int32_t> ValueSequenceInt32() const override {
return sequenceWithValue<int32_t>(42);
}
WebVector<uint32_t> ValueSequenceUint32() const override {
return sequenceWithValue<uint32_t>(42);
}
WebVector<int64_t> ValueSequenceInt64() const override {
return sequenceWithValue<int64_t>(42);
}
WebVector<uint64_t> ValueSequenceUint64() const override {
return sequenceWithValue<uint64_t>(42);
}
WebVector<double> ValueSequenceDouble() const override {
return sequenceWithValue<double>(42.0);
}
blink::WebVector<blink::WebString> ValueSequenceString() const override {
return sequenceWithValue<blink::WebString>(
blink::WebString::FromUTF8("42"));
}
private:
std::string name_;
blink::WebRTCStatsMemberType type_;
};
class MockWebRTCStats : public blink::WebRTCStats {
public:
MockWebRTCStats(const std::string& id,
const std::string& type,
double timestamp)
: id_(id), type_(type), timestamp_(timestamp) {}
void addMember(const std::string& name, blink::WebRTCStatsMemberType type) {
members_.push_back(std::make_pair(name, type));
}
// blink::WebRTCStats overrides.
blink::WebString Id() const override {
return blink::WebString::FromUTF8(id_);
}
blink::WebString GetType() const override {
return blink::WebString::FromUTF8(type_);
}
double Timestamp() const override { return timestamp_; }
size_t MembersCount() const override { return members_.size(); }
std::unique_ptr<WebRTCStatsMember> GetMember(size_t i) const override {
return std::unique_ptr<WebRTCStatsMember>(
new MockWebRTCStatsMember(members_[i].first, members_[i].second));
}
private:
std::string id_;
std::string type_;
double timestamp_;
std::vector<std::pair<std::string, blink::WebRTCStatsMemberType>> members_;
};
class MockWebRTCStatsReport : public blink::WebRTCStatsReport {
public:
MockWebRTCStatsReport() : i_(0) {}
MockWebRTCStatsReport(const MockWebRTCStatsReport& other)
: stats_(other.stats_), i_(0) {}
void AddStats(const MockWebRTCStats& stats) { stats_.push_back(stats); }
// blink::WebRTCStatsReport overrides.
std::unique_ptr<blink::WebRTCStatsReport> CopyHandle() const override {
// Because this is just a mock, we copy the underlying stats instead of
// referencing the same stats as the original report.
return std::unique_ptr<blink::WebRTCStatsReport>(
new MockWebRTCStatsReport(*this));
}
std::unique_ptr<WebRTCStats> GetStats(WebString id) const override {
for (const MockWebRTCStats& stats : stats_) {
if (stats.Id() == id)
return std::unique_ptr<blink::WebRTCStats>(new MockWebRTCStats(stats));
}
return nullptr;
}
std::unique_ptr<blink::WebRTCStats> Next() override {
if (i_ >= stats_.size())
return nullptr;
return std::unique_ptr<blink::WebRTCStats>(
new MockWebRTCStats(stats_[i_++]));
}
size_t Size() const override { return stats_.size(); }
private:
std::vector<MockWebRTCStats> stats_;
size_t i_;
};
class MockWebRTCRtpSender : public blink::WebRTCRtpSender {
public:
MockWebRTCRtpSender(uintptr_t id,
std::unique_ptr<blink::WebMediaStreamTrack> track)
: id_(id), track_(std::move(track)) {}
uintptr_t Id() const override { return id_; }
const blink::WebMediaStreamTrack* Track() const override {
return track_.get();
}
void SetTrack(std::unique_ptr<blink::WebMediaStreamTrack> track) {
track_ = std::move(track);
}
private:
uintptr_t id_;
std::unique_ptr<blink::WebMediaStreamTrack> track_;
};
class MockWebRTCRtpContributingSource
: public blink::WebRTCRtpContributingSource {
public:
MockWebRTCRtpContributingSource(
blink::WebRTCRtpContributingSourceType source_type,
double timestamp_ms,
uint32_t source)
: source_type_(source_type),
timestamp_ms_(timestamp_ms),
source_(source) {}
~MockWebRTCRtpContributingSource() override {}
blink::WebRTCRtpContributingSourceType SourceType() const override {
return source_type_;
}
double TimestampMs() const override { return timestamp_ms_; }
uint32_t Source() const override { return source_; }
private:
blink::WebRTCRtpContributingSourceType source_type_;
double timestamp_ms_;
uint32_t source_;
};
class MockWebRTCRtpReceiver : public blink::WebRTCRtpReceiver {
public:
MockWebRTCRtpReceiver(uintptr_t id, const blink::WebMediaStreamTrack& track)
: id_(id), track_(track), num_packets_(0) {}
~MockWebRTCRtpReceiver() override {}
uintptr_t Id() const override { return id_; }
const blink::WebMediaStreamTrack& Track() const override { return track_; }
// Every time called, mocks that a new packet has arrived updating the i-th
// CSRC such that the |kNumCSRCsActive| latest updated CSRCs are returned. "i"
// is the sequence number modulo number of CSRCs. Also returns an SSRC with
// the latest timestamp. For example, if 2 out of 3 CSRCs should be active,
// this will return the following "(type, source, timestamp)":
// - 1st call: { (CSRC, 0, 0), (SSRC, 0, 0) }
// - 2nd call: { (CSRC, 0, 0000), (CSRC, 1, 5000), (SSRC, 0, 5000) }
// - 3rd call: { (CSRC, 1, 5000), (CSRC, 2, 10000), (SSRC, 0, 10000) }
// - 4th call: { (CSRC, 2, 10000), (CSRC, 0, 15000), (SSRC, 0, 15000) }
// RTCPeerConnection-getReceivers.html depends on this behavior.
blink::WebVector<std::unique_ptr<blink::WebRTCRtpContributingSource>>
GetSources() override {
++num_packets_;
size_t num_csrcs = std::min(kNumCSRCsActive, num_packets_);
blink::WebVector<std::unique_ptr<blink::WebRTCRtpContributingSource>>
contributing_sources(num_csrcs + 1);
for (size_t i = 0; i < num_csrcs; ++i) {
size_t sequence_number = num_packets_ - num_csrcs + i;
contributing_sources[i] =
base::MakeUnique<MockWebRTCRtpContributingSource>(
blink::WebRTCRtpContributingSourceType::CSRC,
// Return value should include timestamps for the last 10 seconds,
// we pretend |10000.0 / kNumCSRCsActive| milliseconds have passed
// per packet in the sequence, starting from 0. This is not
// relative to any real clock.
sequence_number * 10000.0 / kNumCSRCsActive,
sequence_number % kNumCSRCs);
}
contributing_sources[num_csrcs] =
base::MakeUnique<MockWebRTCRtpContributingSource>(
blink::WebRTCRtpContributingSourceType::SSRC,
contributing_sources[num_csrcs - 1]->TimestampMs(), 0);
return contributing_sources;
}
private:
const size_t kNumCSRCs = 3;
const size_t kNumCSRCsActive = 2;
uintptr_t id_;
blink::WebMediaStreamTrack track_;
size_t num_packets_;
};
blink::WebVector<std::unique_ptr<blink::WebRTCRtpReceiver>>
GetReceiversOfStream(const blink::WebMediaStream& remote_web_stream,
std::map<std::string, uintptr_t>* id_by_track) {
std::vector<std::unique_ptr<blink::WebRTCRtpReceiver>> receivers;
blink::WebVector<blink::WebMediaStreamTrack> remote_tracks;
remote_web_stream.AudioTracks(remote_tracks);
for (const auto& remote_track : remote_tracks) {
receivers.push_back(
std::unique_ptr<blink::WebRTCRtpReceiver>(new MockWebRTCRtpReceiver(
GetIDByTrack(remote_track.Id().Utf8(), id_by_track),
remote_track)));
}
remote_web_stream.VideoTracks(remote_tracks);
for (const auto& remote_track : remote_tracks) {
receivers.push_back(
std::unique_ptr<blink::WebRTCRtpReceiver>(new MockWebRTCRtpReceiver(
GetIDByTrack(remote_track.Id().Utf8(), id_by_track),
remote_track)));
}
blink::WebVector<std::unique_ptr<blink::WebRTCRtpReceiver>> result(
receivers.size());
for (size_t i = 0; i < receivers.size(); ++i) {
result[i] = std::move(receivers[i]);
}
return result;
}
} // namespace
MockWebRTCPeerConnectionHandler::MockWebRTCPeerConnectionHandler()
: weak_factory_(this) {}
MockWebRTCPeerConnectionHandler::~MockWebRTCPeerConnectionHandler() {}
MockWebRTCPeerConnectionHandler::MockWebRTCPeerConnectionHandler(
WebRTCPeerConnectionHandlerClient* client,
TestInterfaces* interfaces)
: client_(client),
stopped_(false),
stream_count_(0),
interfaces_(interfaces),
weak_factory_(this) {}
void MockWebRTCPeerConnectionHandler::ReportInitializeCompleted() {
client_->DidChangeICEGatheringState(
WebRTCPeerConnectionHandlerClient::kICEGatheringStateComplete);
client_->DidChangeICEConnectionState(
WebRTCPeerConnectionHandlerClient::kICEConnectionStateCompleted);
}
bool MockWebRTCPeerConnectionHandler::Initialize(
const WebRTCConfiguration& configuration,
const WebMediaConstraints& constraints) {
interfaces_->GetDelegate()->PostTask(
base::Bind(&MockWebRTCPeerConnectionHandler::ReportInitializeCompleted,
weak_factory_.GetWeakPtr()));
return true;
}
void MockWebRTCPeerConnectionHandler::CreateOffer(
const WebRTCSessionDescriptionRequest& request,
const WebMediaConstraints& constraints) {
PostRequestFailure(request);
}
void MockWebRTCPeerConnectionHandler::PostRequestResult(
const WebRTCSessionDescriptionRequest& request,
const WebRTCSessionDescription& session_description) {
interfaces_->GetDelegate()->PostTask(
base::Bind(&WebRTCSessionDescriptionRequest::RequestSucceeded,
base::Owned(new WebRTCSessionDescriptionRequest(request)),
session_description));
}
void MockWebRTCPeerConnectionHandler::PostRequestFailure(
const WebRTCSessionDescriptionRequest& request) {
interfaces_->GetDelegate()->PostTask(
base::Bind(&WebRTCSessionDescriptionRequest::RequestFailed,
base::Owned(new WebRTCSessionDescriptionRequest(request)),
WebString("TEST_ERROR")));
}
void MockWebRTCPeerConnectionHandler::PostRequestResult(
const WebRTCVoidRequest& request) {
interfaces_->GetDelegate()->PostTask(
base::Bind(&WebRTCVoidRequest::RequestSucceeded,
base::Owned(new WebRTCVoidRequest(request))));
}
void MockWebRTCPeerConnectionHandler::PostRequestFailure(
const WebRTCVoidRequest& request) {
interfaces_->GetDelegate()->PostTask(base::Bind(
&WebRTCVoidRequest::RequestFailed,
base::Owned(new WebRTCVoidRequest(request)), WebString("TEST_ERROR")));
}
void MockWebRTCPeerConnectionHandler::CreateOffer(
const WebRTCSessionDescriptionRequest& request,
const blink::WebRTCOfferOptions& options) {
if (options.IceRestart() && options.VoiceActivityDetection() &&
options.OfferToReceiveAudio() > 0 && options.OfferToReceiveVideo() > 0) {
WebRTCSessionDescription session_description;
session_description.Initialize("offer", "local");
PostRequestResult(request, session_description);
} else {
PostRequestFailure(request);
}
}
void MockWebRTCPeerConnectionHandler::CreateAnswer(
const WebRTCSessionDescriptionRequest& request,
const WebMediaConstraints& constraints) {
if (!remote_description_.IsNull()) {
WebRTCSessionDescription session_description;
session_description.Initialize("answer", "local");
PostRequestResult(request, session_description);
} else {
PostRequestFailure(request);
}
}
void MockWebRTCPeerConnectionHandler::CreateAnswer(
const WebRTCSessionDescriptionRequest& request,
const blink::WebRTCAnswerOptions& options) {
if (options.VoiceActivityDetection()) {
WebRTCSessionDescription session_description;
session_description.Initialize("answer", "local");
PostRequestResult(request, session_description);
} else {
PostRequestFailure(request);
}
}
void MockWebRTCPeerConnectionHandler::SetLocalDescription(
const WebRTCVoidRequest& request,
const WebRTCSessionDescription& local_description) {
if (!local_description.IsNull() && local_description.Sdp() == "local") {
local_description_ = local_description;
PostRequestResult(request);
} else {
PostRequestFailure(request);
}
}
void MockWebRTCPeerConnectionHandler::SetRemoteDescription(
const WebRTCVoidRequest& request,
const WebRTCSessionDescription& remote_description) {
if (!remote_description.IsNull() && remote_description.Sdp() == "remote") {
remote_description_ = remote_description;
// This ensures the promise is resolved before the remote stream event is
// fired. This may change in the future, see
// https://github.com/w3c/webrtc-pc/issues/1508.
interfaces_->GetDelegate()->PostTask(
base::Bind(&MockWebRTCPeerConnectionHandler::UpdateRemoteStreams,
weak_factory_.GetWeakPtr()));
PostRequestResult(request);
} else
PostRequestFailure(request);
}
void MockWebRTCPeerConnectionHandler::UpdateRemoteStreams() {
// Find all removed streams.
// Set the readyState of the remote tracks to ended, remove them from the
// stream and notify the client.
StreamMap::iterator removed_it = remote_streams_.begin();
while (removed_it != remote_streams_.end()) {
if (local_streams_.find(removed_it->first) != local_streams_.end()) {
removed_it++;
continue;
}
// The stream have been removed. Loop through all tracks and set the
// source as ended and remove them from the stream.
blink::WebMediaStream stream = removed_it->second;
blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
stream.AudioTracks(audio_tracks);
for (size_t i = 0; i < audio_tracks.size(); ++i) {
audio_tracks[i].Source().SetReadyState(
blink::WebMediaStreamSource::kReadyStateEnded);
stream.RemoveTrack(audio_tracks[i]);
}
blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
stream.VideoTracks(video_tracks);
for (size_t i = 0; i < video_tracks.size(); ++i) {
video_tracks[i].Source().SetReadyState(
blink::WebMediaStreamSource::kReadyStateEnded);
stream.RemoveTrack(video_tracks[i]);
}
client_->DidRemoveRemoteStream(stream);
remote_streams_.erase(removed_it++);
}
// Find all new streams;
// Create new sources and tracks and notify the client about the new stream.
StreamMap::iterator added_it = local_streams_.begin();
while (added_it != local_streams_.end()) {
if (remote_streams_.find(added_it->first) != remote_streams_.end()) {
added_it++;
continue;
}
const blink::WebMediaStream& stream = added_it->second;
blink::WebVector<blink::WebMediaStreamTrack> local_audio_tracks;
stream.AudioTracks(local_audio_tracks);
blink::WebVector<blink::WebMediaStreamTrack> remote_audio_tracks(
local_audio_tracks.size());
for (size_t i = 0; i < local_audio_tracks.size(); ++i) {
blink::WebMediaStreamSource webkit_source;
webkit_source.Initialize(local_audio_tracks[i].Id(),
blink::WebMediaStreamSource::kTypeAudio,
local_audio_tracks[i].Id(), true /* remote */);
remote_audio_tracks[i].Initialize(webkit_source);
}
blink::WebVector<blink::WebMediaStreamTrack> local_video_tracks;
stream.VideoTracks(local_video_tracks);
blink::WebVector<blink::WebMediaStreamTrack> remote_video_tracks(
local_video_tracks.size());
for (size_t i = 0; i < local_video_tracks.size(); ++i) {
blink::WebMediaStreamSource webkit_source;
webkit_source.Initialize(local_video_tracks[i].Id(),
blink::WebMediaStreamSource::kTypeVideo,
local_video_tracks[i].Id(), true /* remote */);
remote_video_tracks[i].Initialize(webkit_source);
}
blink::WebMediaStream new_remote_stream;
new_remote_stream.Initialize(remote_audio_tracks, remote_video_tracks);
remote_streams_[added_it->first] = new_remote_stream;
blink::WebVector<std::unique_ptr<blink::WebRTCRtpReceiver>> receivers =
GetReceiversOfStream(new_remote_stream, &id_by_track_);
client_->DidAddRemoteStream(new_remote_stream, &receivers);
++added_it;
}
}
WebRTCSessionDescription MockWebRTCPeerConnectionHandler::LocalDescription() {
return local_description_;
}
WebRTCSessionDescription MockWebRTCPeerConnectionHandler::RemoteDescription() {
return remote_description_;
}
WebRTCErrorType MockWebRTCPeerConnectionHandler::SetConfiguration(
const WebRTCConfiguration& configuration) {
return WebRTCErrorType::kNone;
}
bool MockWebRTCPeerConnectionHandler::AddICECandidate(
const WebRTCICECandidate& ice_candidate) {
client_->DidGenerateICECandidate(ice_candidate);
return true;
}
bool MockWebRTCPeerConnectionHandler::AddICECandidate(
const WebRTCVoidRequest& request,
const WebRTCICECandidate& ice_candidate) {
PostRequestResult(request);
return true;
}
bool MockWebRTCPeerConnectionHandler::AddStream(
const WebMediaStream& stream,
const WebMediaConstraints& constraints) {
if (local_streams_.find(stream.Id().Utf8()) != local_streams_.end())
return false;
++stream_count_;
client_->NegotiationNeeded();
local_streams_[stream.Id().Utf8()] = stream;
return true;
}
void MockWebRTCPeerConnectionHandler::RemoveStream(
const WebMediaStream& stream) {
--stream_count_;
local_streams_.erase(stream.Id().Utf8());
client_->NegotiationNeeded();
}
void MockWebRTCPeerConnectionHandler::GetStats(
const WebRTCStatsRequest& request) {
WebRTCStatsResponse response = request.CreateResponse();
double current_date =
interfaces_->GetDelegate()->GetCurrentTimeInMillisecond();
if (request.HasSelector()) {
// FIXME: There is no check that the fetched values are valid.
MockWebRTCLegacyStats stats("Mock video", "ssrc", current_date);
stats.addStatistic("type", "video");
response.AddStats(stats);
} else {
for (int i = 0; i < stream_count_; ++i) {
MockWebRTCLegacyStats audio_stats("Mock audio", "ssrc", current_date);
audio_stats.addStatistic("type", "audio");
response.AddStats(audio_stats);
MockWebRTCLegacyStats video_stats("Mock video", "ssrc", current_date);
video_stats.addStatistic("type", "video");
response.AddStats(video_stats);
}
}
interfaces_->GetDelegate()->PostTask(
base::Bind(&blink::WebRTCStatsRequest::RequestSucceeded,
base::Owned(new WebRTCStatsRequest(request)), response));
}
void MockWebRTCPeerConnectionHandler::GetStats(
std::unique_ptr<blink::WebRTCStatsReportCallback> callback) {
std::unique_ptr<MockWebRTCStatsReport> report(new MockWebRTCStatsReport());
MockWebRTCStats stats("mock-stats-01", "mock-stats", 1234.0);
stats.addMember("bool", blink::kWebRTCStatsMemberTypeBool);
stats.addMember("int32", blink::kWebRTCStatsMemberTypeInt32);
stats.addMember("uint32", blink::kWebRTCStatsMemberTypeUint32);
stats.addMember("int64", blink::kWebRTCStatsMemberTypeInt64);
stats.addMember("uint64", blink::kWebRTCStatsMemberTypeUint64);
stats.addMember("double", blink::kWebRTCStatsMemberTypeDouble);
stats.addMember("string", blink::kWebRTCStatsMemberTypeString);
stats.addMember("sequenceBool", blink::kWebRTCStatsMemberTypeSequenceBool);
stats.addMember("sequenceInt32", blink::kWebRTCStatsMemberTypeSequenceInt32);
stats.addMember("sequenceUint32",
blink::kWebRTCStatsMemberTypeSequenceUint32);
stats.addMember("sequenceInt64", blink::kWebRTCStatsMemberTypeSequenceInt64);
stats.addMember("sequenceUint64",
blink::kWebRTCStatsMemberTypeSequenceUint64);
stats.addMember("sequenceDouble",
blink::kWebRTCStatsMemberTypeSequenceDouble);
stats.addMember("sequenceString",
blink::kWebRTCStatsMemberTypeSequenceString);
report->AddStats(stats);
callback->OnStatsDelivered(
std::unique_ptr<blink::WebRTCStatsReport>(report.release()));
}
blink::WebVector<std::unique_ptr<blink::WebRTCRtpSender>>
MockWebRTCPeerConnectionHandler::GetSenders() {
std::vector<std::unique_ptr<blink::WebRTCRtpSender>> senders;
// Senders of tracks in |local_streams_| (from |Add/RemoveStream|).
for (const auto& pair : local_streams_) {
const auto& local_stream = pair.second;
blink::WebVector<blink::WebMediaStreamTrack> local_tracks;
local_stream.AudioTracks(local_tracks);
for (const auto& local_track : local_tracks) {
senders.push_back(
std::unique_ptr<blink::WebRTCRtpSender>(new MockWebRTCRtpSender(
GetIDByTrack(local_track.Id().Utf8(), &id_by_track_),
base::MakeUnique<WebMediaStreamTrack>(local_track))));
}
local_stream.VideoTracks(local_tracks);
for (const auto& local_track : local_tracks) {
senders.push_back(
std::unique_ptr<blink::WebRTCRtpSender>(new MockWebRTCRtpSender(
GetIDByTrack(local_track.Id().Utf8(), &id_by_track_),
base::MakeUnique<WebMediaStreamTrack>(local_track))));
}
}
// Senders of tracks in |tracks_| (from |Add/RemoveTrack|).
for (const auto& pair : tracks_) {
const auto& track = pair.second;
bool has_sender_for_track = false;
for (const auto& sender : senders) {
if (sender->Track()->Id() == track.Id()) {
has_sender_for_track = true;
break;
}
}
if (has_sender_for_track)
continue;
senders.push_back(base::MakeUnique<MockWebRTCRtpSender>(
GetIDByTrack(track.Id().Utf8(), &id_by_track_),
base::MakeUnique<WebMediaStreamTrack>(track)));
}
blink::WebVector<std::unique_ptr<blink::WebRTCRtpSender>> web_vector(
senders.size());
for (size_t i = 0; i < senders.size(); ++i) {
web_vector[i] = std::move(senders[i]);
}
return web_vector;
}
blink::WebVector<std::unique_ptr<blink::WebRTCRtpReceiver>>
MockWebRTCPeerConnectionHandler::GetReceivers() {
std::vector<std::unique_ptr<blink::WebRTCRtpReceiver>> receivers;
for (const auto& pair : remote_streams_) {
const auto& remote_stream = pair.second;
for (auto& receiver : GetReceiversOfStream(remote_stream, &id_by_track_)) {
receivers.push_back(std::move(receiver));
}
}
blink::WebVector<std::unique_ptr<blink::WebRTCRtpReceiver>> web_vector(
receivers.size());
for (size_t i = 0; i < receivers.size(); ++i) {
web_vector[i] = std::move(receivers[i]);
}
return web_vector;
}
std::unique_ptr<blink::WebRTCRtpSender>
MockWebRTCPeerConnectionHandler::AddTrack(
const blink::WebMediaStreamTrack& web_track,
const blink::WebVector<blink::WebMediaStream>& web_streams) {
for (const auto& sender : GetSenders()) {
if (sender->Track() && sender->Track()->Id() == web_track.Id()) {
return nullptr;
}
}
tracks_[web_track.Id().Utf8()] = web_track;
client_->NegotiationNeeded();
return base::MakeUnique<MockWebRTCRtpSender>(
GetIDByTrack(web_track.Id().Utf8(), &id_by_track_),
base::MakeUnique<blink::WebMediaStreamTrack>(web_track));
}
bool MockWebRTCPeerConnectionHandler::RemoveTrack(
blink::WebRTCRtpSender* web_sender) {
if (!tracks_.erase(web_sender->Track()->Id().Utf8()))
return false;
MockWebRTCRtpSender* sender = static_cast<MockWebRTCRtpSender*>(web_sender);
sender->SetTrack(nullptr);
client_->NegotiationNeeded();
return true;
}
void MockWebRTCPeerConnectionHandler::ReportCreationOfDataChannel() {
WebRTCDataChannelInit init;
WebRTCDataChannelHandler* remote_data_channel =
new MockWebRTCDataChannelHandler("MockRemoteDataChannel", init,
interfaces_->GetDelegate());
client_->DidAddRemoteDataChannel(remote_data_channel);
}
WebRTCDataChannelHandler* MockWebRTCPeerConnectionHandler::CreateDataChannel(
const WebString& label,
const blink::WebRTCDataChannelInit& init) {
interfaces_->GetDelegate()->PostTask(
base::Bind(&MockWebRTCPeerConnectionHandler::ReportCreationOfDataChannel,
weak_factory_.GetWeakPtr()));
// TODO(lukasza): Unclear if it is okay to return a different object than the
// one created in ReportCreationOfDataChannel.
return new MockWebRTCDataChannelHandler(label, init,
interfaces_->GetDelegate());
}
WebRTCDTMFSenderHandler* MockWebRTCPeerConnectionHandler::CreateDTMFSender(
const WebMediaStreamTrack& track) {
return new MockWebRTCDTMFSenderHandler(track, interfaces_->GetDelegate());
}
void MockWebRTCPeerConnectionHandler::Stop() {
stopped_ = true;
weak_factory_.InvalidateWeakPtrs();
}
} // namespace test_runner