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<rtc::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  rtc::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 rtc::RefCountedObject<MockStreamCollection>),
211      remote_streams_(new rtc::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
224rtc::scoped_refptr<webrtc::StreamCollectionInterface>
225MockPeerConnectionImpl::local_streams() {
226  return local_streams_;
227}
228
229rtc::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
250rtc::scoped_refptr<DtmfSenderInterface>
251MockPeerConnectionImpl::CreateDtmfSender(AudioTrackInterface* track) {
252  if (!track) {
253    return NULL;
254  }
255  return new rtc::RefCountedObject<MockDtmfSender>(track);
256}
257
258rtc::scoped_refptr<webrtc::DataChannelInterface>
259MockPeerConnectionImpl::CreateDataChannel(const std::string& label,
260                      const webrtc::DataChannelInit* config) {
261  return new rtc::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  webrtc::StatsReport report1, report2;
273  report1.id = "1234";
274  report1.type = "ssrc";
275  report1.timestamp = 42;
276  report1.values.push_back(
277      webrtc::StatsReport::Value(
278          webrtc::StatsReport::kStatsValueNameFingerprint,
279          "trackvalue"));
280
281  webrtc::StatsReports reports;
282  reports.push_back(&report1);
283
284  // If selector is given, we pass back one report.
285  // If selector is not given, we pass back two.
286  if (!track) {
287    report2.id = "nontrack";
288    report2.type = "generic";
289    report2.timestamp = 44;
290    report2.values.push_back(
291        webrtc::StatsReport::Value(
292            webrtc::StatsReport::kStatsValueNameFingerprintAlgorithm,
293            "somevalue"));
294    reports.push_back(&report2);
295  }
296
297  // Note that the callback is synchronous, not asynchronous; it will
298  // happen before the request call completes.
299  observer->OnComplete(reports);
300
301  return true;
302}
303
304const webrtc::SessionDescriptionInterface*
305MockPeerConnectionImpl::local_description() const {
306  return local_desc_.get();
307}
308
309const webrtc::SessionDescriptionInterface*
310MockPeerConnectionImpl::remote_description() const {
311  return remote_desc_.get();
312}
313
314void MockPeerConnectionImpl::AddRemoteStream(MediaStreamInterface* stream) {
315  remote_streams_->AddStream(stream);
316}
317
318void MockPeerConnectionImpl::CreateOffer(
319    CreateSessionDescriptionObserver* observer,
320    const MediaConstraintsInterface* constraints) {
321  DCHECK(observer);
322  created_sessiondescription_.reset(
323      dependency_factory_->CreateSessionDescription("unknown", kDummyOffer,
324                                                    NULL));
325}
326
327void MockPeerConnectionImpl::CreateAnswer(
328    CreateSessionDescriptionObserver* observer,
329    const MediaConstraintsInterface* constraints) {
330  DCHECK(observer);
331  created_sessiondescription_.reset(
332      dependency_factory_->CreateSessionDescription("unknown", kDummyAnswer,
333                                                    NULL));
334}
335
336void MockPeerConnectionImpl::SetLocalDescriptionWorker(
337    SetSessionDescriptionObserver* observer,
338    SessionDescriptionInterface* desc) {
339  desc->ToString(&description_sdp_);
340  local_desc_.reset(desc);
341}
342
343void MockPeerConnectionImpl::SetRemoteDescriptionWorker(
344    SetSessionDescriptionObserver* observer,
345    SessionDescriptionInterface* desc) {
346  desc->ToString(&description_sdp_);
347  remote_desc_.reset(desc);
348}
349
350bool MockPeerConnectionImpl::UpdateIce(
351    const IceServers& configuration,
352    const MediaConstraintsInterface* constraints) {
353  return true;
354}
355
356bool MockPeerConnectionImpl::AddIceCandidate(
357    const IceCandidateInterface* candidate) {
358  sdp_mid_ = candidate->sdp_mid();
359  sdp_mline_index_ = candidate->sdp_mline_index();
360  return candidate->ToString(&ice_sdp_);
361}
362
363void MockPeerConnectionImpl::RegisterUMAObserver(
364    webrtc::UMAObserver* observer) {
365  NOTIMPLEMENTED();
366}
367
368}  // namespace content
369