1// Copyright (c) 2012 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 "content/renderer/media/mock_peer_connection_impl.h"
6
7#include <vector>
8
9#include "base/logging.h"
10#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
11
12using testing::_;
13using webrtc::AudioTrackInterface;
14using webrtc::CreateSessionDescriptionObserver;
15using webrtc::DtmfSenderInterface;
16using webrtc::DtmfSenderObserverInterface;
17using webrtc::IceCandidateInterface;
18using webrtc::MediaConstraintsInterface;
19using webrtc::MediaStreamInterface;
20using webrtc::PeerConnectionInterface;
21using webrtc::SessionDescriptionInterface;
22using webrtc::SetSessionDescriptionObserver;
23
24namespace content {
25
26class MockStreamCollection : public webrtc::StreamCollectionInterface {
27 public:
28  virtual size_t count() OVERRIDE {
29    return streams_.size();
30  }
31  virtual MediaStreamInterface* at(size_t index) OVERRIDE {
32    return streams_[index];
33  }
34  virtual MediaStreamInterface* find(const std::string& label) OVERRIDE {
35    for (size_t i = 0; i < streams_.size(); ++i) {
36      if (streams_[i]->label() == label)
37        return streams_[i];
38    }
39    return NULL;
40  }
41  virtual webrtc::MediaStreamTrackInterface* FindAudioTrack(
42      const std::string& id) OVERRIDE {
43    for (size_t i = 0; i < streams_.size(); ++i) {
44      webrtc::MediaStreamTrackInterface* track =
45          streams_.at(i)->FindAudioTrack(id);
46      if (track)
47        return track;
48    }
49    return NULL;
50  }
51  virtual webrtc::MediaStreamTrackInterface* FindVideoTrack(
52      const std::string& id) OVERRIDE {
53    for (size_t i = 0; i < streams_.size(); ++i) {
54      webrtc::MediaStreamTrackInterface* track =
55          streams_.at(i)->FindVideoTrack(id);
56      if (track)
57        return track;
58    }
59    return NULL;
60  }
61  void AddStream(MediaStreamInterface* stream) {
62    streams_.push_back(stream);
63  }
64  void RemoveStream(MediaStreamInterface* stream) {
65    StreamVector::iterator it = streams_.begin();
66    for (; it != streams_.end(); ++it) {
67      if (it->get() == stream) {
68        streams_.erase(it);
69        break;
70      }
71    }
72  }
73
74 protected:
75  virtual ~MockStreamCollection() {}
76
77 private:
78  typedef std::vector<talk_base::scoped_refptr<MediaStreamInterface> >
79      StreamVector;
80  StreamVector streams_;
81};
82
83class MockDataChannel : public webrtc::DataChannelInterface {
84 public:
85  MockDataChannel(const std::string& label,
86                  const webrtc::DataChannelInit* config)
87      : label_(label),
88        reliable_(config->reliable),
89        state_(webrtc::DataChannelInterface::kConnecting),
90        config_(*config) {
91  }
92
93  virtual void RegisterObserver(
94      webrtc::DataChannelObserver* observer) OVERRIDE {
95  }
96
97  virtual void UnregisterObserver() OVERRIDE {
98  }
99
100  virtual std::string label() const OVERRIDE {
101    return label_;
102  }
103
104  virtual bool reliable() const OVERRIDE {
105    return reliable_;
106  }
107
108  virtual bool ordered() const OVERRIDE {
109    return config_.ordered;
110  }
111
112  virtual unsigned short maxRetransmitTime() const OVERRIDE {
113    return config_.maxRetransmitTime;
114  }
115
116  virtual unsigned short maxRetransmits() const OVERRIDE {
117    return config_.maxRetransmits;
118  }
119
120  virtual std::string protocol() const OVERRIDE {
121    return config_.protocol;
122  }
123
124  virtual bool negotiated() const OVERRIDE {
125    return config_.negotiated;
126  }
127
128  virtual int id() const OVERRIDE {
129    NOTIMPLEMENTED();
130    return 0;
131  }
132
133  virtual DataState state() const OVERRIDE {
134    return state_;
135  }
136
137  virtual uint64 buffered_amount() const OVERRIDE {
138    NOTIMPLEMENTED();
139    return 0;
140  }
141
142  virtual void Close() OVERRIDE {
143    state_ = webrtc::DataChannelInterface::kClosing;
144  }
145
146  virtual bool Send(const webrtc::DataBuffer& buffer) OVERRIDE {
147    return state_ == webrtc::DataChannelInterface::kOpen;
148  }
149
150 protected:
151  virtual ~MockDataChannel() {}
152
153 private:
154  std::string label_;
155  bool reliable_;
156  webrtc::DataChannelInterface::DataState state_;
157  webrtc::DataChannelInit config_;
158};
159
160class MockDtmfSender : public DtmfSenderInterface {
161 public:
162  explicit MockDtmfSender(AudioTrackInterface* track)
163      : track_(track),
164        observer_(NULL),
165        duration_(0),
166        inter_tone_gap_(0) {}
167  virtual void RegisterObserver(
168      DtmfSenderObserverInterface* observer) OVERRIDE {
169    observer_ = observer;
170  }
171  virtual void UnregisterObserver() OVERRIDE {
172    observer_ = NULL;
173  }
174  virtual bool CanInsertDtmf() OVERRIDE {
175    return true;
176  }
177  virtual bool InsertDtmf(const std::string& tones, int duration,
178                          int inter_tone_gap) OVERRIDE {
179    tones_ = tones;
180    duration_ = duration;
181    inter_tone_gap_ = inter_tone_gap;
182    return true;
183  }
184  virtual const AudioTrackInterface* track() const OVERRIDE {
185    return track_.get();
186  }
187  virtual std::string tones() const OVERRIDE {
188    return tones_;
189  }
190  virtual int duration() const OVERRIDE { return duration_; }
191  virtual int inter_tone_gap() const OVERRIDE { return inter_tone_gap_; }
192
193 protected:
194  virtual ~MockDtmfSender() {}
195
196 private:
197  talk_base::scoped_refptr<AudioTrackInterface> track_;
198  DtmfSenderObserverInterface* observer_;
199  std::string tones_;
200  int duration_;
201  int inter_tone_gap_;
202};
203
204const char MockPeerConnectionImpl::kDummyOffer[] = "dummy offer";
205const char MockPeerConnectionImpl::kDummyAnswer[] = "dummy answer";
206
207MockPeerConnectionImpl::MockPeerConnectionImpl(
208    MockPeerConnectionDependencyFactory* factory)
209    : dependency_factory_(factory),
210      local_streams_(new talk_base::RefCountedObject<MockStreamCollection>),
211      remote_streams_(new talk_base::RefCountedObject<MockStreamCollection>),
212      hint_audio_(false),
213      hint_video_(false),
214      getstats_result_(true),
215      sdp_mline_index_(-1) {
216  ON_CALL(*this, SetLocalDescription(_, _)).WillByDefault(testing::Invoke(
217      this, &MockPeerConnectionImpl::SetLocalDescriptionWorker));
218  ON_CALL(*this, SetRemoteDescription(_, _)).WillByDefault(testing::Invoke(
219      this, &MockPeerConnectionImpl::SetRemoteDescriptionWorker));
220}
221
222MockPeerConnectionImpl::~MockPeerConnectionImpl() {}
223
224talk_base::scoped_refptr<webrtc::StreamCollectionInterface>
225MockPeerConnectionImpl::local_streams() {
226  return local_streams_;
227}
228
229talk_base::scoped_refptr<webrtc::StreamCollectionInterface>
230MockPeerConnectionImpl::remote_streams() {
231  return remote_streams_;
232}
233
234bool MockPeerConnectionImpl::AddStream(
235    MediaStreamInterface* local_stream,
236    const MediaConstraintsInterface* constraints) {
237  DCHECK(stream_label_.empty());
238  stream_label_ = local_stream->label();
239  local_streams_->AddStream(local_stream);
240  return true;
241}
242
243void MockPeerConnectionImpl::RemoveStream(
244    MediaStreamInterface* local_stream) {
245  DCHECK_EQ(stream_label_, local_stream->label());
246  stream_label_.clear();
247  local_streams_->RemoveStream(local_stream);
248}
249
250talk_base::scoped_refptr<DtmfSenderInterface>
251MockPeerConnectionImpl::CreateDtmfSender(AudioTrackInterface* track) {
252  if (!track) {
253    return NULL;
254  }
255  return new talk_base::RefCountedObject<MockDtmfSender>(track);
256}
257
258talk_base::scoped_refptr<webrtc::DataChannelInterface>
259MockPeerConnectionImpl::CreateDataChannel(const std::string& label,
260                      const webrtc::DataChannelInit* config) {
261  return new talk_base::RefCountedObject<MockDataChannel>(label, config);
262}
263
264bool MockPeerConnectionImpl::GetStats(
265    webrtc::StatsObserver* observer,
266    webrtc::MediaStreamTrackInterface* track,
267    StatsOutputLevel level) {
268  if (!getstats_result_)
269    return false;
270
271  DCHECK_EQ(kStatsOutputLevelStandard, level);
272  std::vector<webrtc::StatsReport> reports(track ? 1 : 2);
273  webrtc::StatsReport& report = reports[0];
274  report.id = "1234";
275  report.type = "ssrc";
276  report.timestamp = 42;
277  webrtc::StatsReport::Value value;
278  value.name = "trackname";
279  value.value = "trackvalue";
280  report.values.push_back(value);
281  // If selector is given, we pass back one report.
282  // If selector is not given, we pass back two.
283  if (!track) {
284    webrtc::StatsReport& report2 = reports[1];
285    report2.id = "nontrack";
286    report2.type = "generic";
287    report2.timestamp = 44;
288    report2.values.push_back(value);
289    value.name = "somename";
290    value.value = "somevalue";
291    report2.values.push_back(value);
292  }
293  // Note that the callback is synchronous, not asynchronous; it will
294  // happen before the request call completes.
295  observer->OnComplete(reports);
296  return true;
297}
298
299const webrtc::SessionDescriptionInterface*
300MockPeerConnectionImpl::local_description() const {
301  return local_desc_.get();
302}
303
304const webrtc::SessionDescriptionInterface*
305MockPeerConnectionImpl::remote_description() const {
306  return remote_desc_.get();
307}
308
309void MockPeerConnectionImpl::AddRemoteStream(MediaStreamInterface* stream) {
310  remote_streams_->AddStream(stream);
311}
312
313void MockPeerConnectionImpl::CreateOffer(
314    CreateSessionDescriptionObserver* observer,
315    const MediaConstraintsInterface* constraints) {
316  DCHECK(observer);
317  created_sessiondescription_.reset(
318      dependency_factory_->CreateSessionDescription("unknown", kDummyOffer,
319                                                    NULL));
320}
321
322void MockPeerConnectionImpl::CreateAnswer(
323    CreateSessionDescriptionObserver* observer,
324    const MediaConstraintsInterface* constraints) {
325  DCHECK(observer);
326  created_sessiondescription_.reset(
327      dependency_factory_->CreateSessionDescription("unknown", kDummyAnswer,
328                                                    NULL));
329}
330
331void MockPeerConnectionImpl::SetLocalDescriptionWorker(
332    SetSessionDescriptionObserver* observer,
333    SessionDescriptionInterface* desc) {
334  desc->ToString(&description_sdp_);
335  local_desc_.reset(desc);
336}
337
338void MockPeerConnectionImpl::SetRemoteDescriptionWorker(
339    SetSessionDescriptionObserver* observer,
340    SessionDescriptionInterface* desc) {
341  desc->ToString(&description_sdp_);
342  remote_desc_.reset(desc);
343}
344
345bool MockPeerConnectionImpl::UpdateIce(
346    const IceServers& configuration,
347    const MediaConstraintsInterface* constraints) {
348  return true;
349}
350
351bool MockPeerConnectionImpl::AddIceCandidate(
352    const IceCandidateInterface* candidate) {
353  sdp_mid_ = candidate->sdp_mid();
354  sdp_mline_index_ = candidate->sdp_mline_index();
355  return candidate->ToString(&ice_sdp_);
356}
357
358void MockPeerConnectionImpl::RegisterUMAObserver(
359    webrtc::UMAObserver* observer) {
360  NOTIMPLEMENTED();
361}
362
363}  // namespace content
364