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_media_stream_dependency_factory.h"
6#include "content/renderer/media/mock_peer_connection_impl.h"
7
8#include <vector>
9
10#include "base/logging.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  }
91
92  virtual void RegisterObserver(
93      webrtc::DataChannelObserver* observer) OVERRIDE {
94  }
95
96  virtual void UnregisterObserver() OVERRIDE {
97  }
98
99  virtual std::string label() const OVERRIDE {
100    return label_;
101  }
102
103  virtual bool reliable() const OVERRIDE {
104    return reliable_;
105  }
106
107  virtual int id() const OVERRIDE {
108    NOTIMPLEMENTED();
109    return 0;
110  }
111
112  virtual DataState state() const OVERRIDE {
113    return state_;
114  }
115
116  virtual uint64 buffered_amount() const OVERRIDE {
117    NOTIMPLEMENTED();
118    return 0;
119  }
120
121  virtual void Close() OVERRIDE {
122    state_ = webrtc::DataChannelInterface::kClosing;
123  }
124
125  virtual bool Send(const webrtc::DataBuffer& buffer) OVERRIDE {
126    return state_ == webrtc::DataChannelInterface::kOpen;
127  }
128
129 protected:
130  virtual ~MockDataChannel() {}
131
132 private:
133  std::string label_;
134  bool reliable_;
135  webrtc::DataChannelInterface::DataState state_;
136};
137
138class MockDtmfSender : public DtmfSenderInterface {
139 public:
140  explicit MockDtmfSender(AudioTrackInterface* track)
141      : track_(track),
142        observer_(NULL),
143        duration_(0),
144        inter_tone_gap_(0) {}
145  virtual void RegisterObserver(
146      DtmfSenderObserverInterface* observer) OVERRIDE {
147    observer_ = observer;
148  }
149  virtual void UnregisterObserver() OVERRIDE {
150    observer_ = NULL;
151  }
152  virtual bool CanInsertDtmf() OVERRIDE {
153    return true;
154  }
155  virtual bool InsertDtmf(const std::string& tones, int duration,
156                          int inter_tone_gap) OVERRIDE {
157    tones_ = tones;
158    duration_ = duration;
159    inter_tone_gap_ = inter_tone_gap;
160    return true;
161  }
162  virtual const AudioTrackInterface* track() const OVERRIDE {
163    return track_.get();
164  }
165  virtual std::string tones() const OVERRIDE {
166    return tones_;
167  }
168  virtual int duration() const OVERRIDE { return duration_; }
169  virtual int inter_tone_gap() const OVERRIDE { return inter_tone_gap_; }
170
171 protected:
172  virtual ~MockDtmfSender() {}
173
174 private:
175  talk_base::scoped_refptr<AudioTrackInterface> track_;
176  DtmfSenderObserverInterface* observer_;
177  std::string tones_;
178  int duration_;
179  int inter_tone_gap_;
180};
181
182const char MockPeerConnectionImpl::kDummyOffer[] = "dummy offer";
183const char MockPeerConnectionImpl::kDummyAnswer[] = "dummy answer";
184
185MockPeerConnectionImpl::MockPeerConnectionImpl(
186    MockMediaStreamDependencyFactory* factory)
187    : dependency_factory_(factory),
188      local_streams_(new talk_base::RefCountedObject<MockStreamCollection>),
189      remote_streams_(new talk_base::RefCountedObject<MockStreamCollection>),
190      hint_audio_(false),
191      hint_video_(false),
192      getstats_result_(true),
193      sdp_mline_index_(-1) {
194  ON_CALL(*this, SetLocalDescription(_, _)).WillByDefault(testing::Invoke(
195      this, &MockPeerConnectionImpl::SetLocalDescriptionWorker));
196  ON_CALL(*this, SetRemoteDescription(_, _)).WillByDefault(testing::Invoke(
197      this, &MockPeerConnectionImpl::SetRemoteDescriptionWorker));
198}
199
200MockPeerConnectionImpl::~MockPeerConnectionImpl() {}
201
202talk_base::scoped_refptr<webrtc::StreamCollectionInterface>
203MockPeerConnectionImpl::local_streams() {
204  return local_streams_;
205}
206
207talk_base::scoped_refptr<webrtc::StreamCollectionInterface>
208MockPeerConnectionImpl::remote_streams() {
209  return remote_streams_;
210}
211
212bool MockPeerConnectionImpl::AddStream(
213    MediaStreamInterface* local_stream,
214    const MediaConstraintsInterface* constraints) {
215  DCHECK(stream_label_.empty());
216  stream_label_ = local_stream->label();
217  local_streams_->AddStream(local_stream);
218  return true;
219}
220
221void MockPeerConnectionImpl::RemoveStream(
222    MediaStreamInterface* local_stream) {
223  DCHECK_EQ(stream_label_, local_stream->label());
224  stream_label_.clear();
225  local_streams_->RemoveStream(local_stream);
226}
227
228talk_base::scoped_refptr<DtmfSenderInterface>
229MockPeerConnectionImpl::CreateDtmfSender(AudioTrackInterface* track) {
230  if (!track) {
231    return NULL;
232  }
233  return new talk_base::RefCountedObject<MockDtmfSender>(track);
234}
235
236talk_base::scoped_refptr<webrtc::DataChannelInterface>
237MockPeerConnectionImpl::CreateDataChannel(const std::string& label,
238                      const webrtc::DataChannelInit* config) {
239  return new talk_base::RefCountedObject<MockDataChannel>(label, config);
240}
241
242bool MockPeerConnectionImpl::GetStats(
243    webrtc::StatsObserver* observer,
244    webrtc::MediaStreamTrackInterface* track) {
245  if (!getstats_result_)
246    return false;
247
248  std::vector<webrtc::StatsReport> reports;
249  webrtc::StatsReport report;
250  report.id = "1234";
251  report.type = "ssrc";
252  report.timestamp = 42;
253  webrtc::StatsReport::Value value;
254  value.name = "trackname";
255  value.value = "trackvalue";
256  report.values.push_back(value);
257  reports.push_back(report);
258  // If selector is given, we pass back one report.
259  // If selector is not given, we pass back two.
260  if (!track) {
261    report.id = "nontrack";
262    report.type = "generic";
263    report.timestamp = 44;
264    value.name = "somename";
265    value.value = "somevalue";
266    report.values.push_back(value);
267    reports.push_back(report);
268  }
269  // Note that the callback is synchronous, not asynchronous; it will
270  // happen before the request call completes.
271  observer->OnComplete(reports);
272  return true;
273}
274
275const webrtc::SessionDescriptionInterface*
276MockPeerConnectionImpl::local_description() const {
277  return local_desc_.get();
278}
279
280const webrtc::SessionDescriptionInterface*
281MockPeerConnectionImpl::remote_description() const {
282  return remote_desc_.get();
283}
284
285void MockPeerConnectionImpl::AddRemoteStream(MediaStreamInterface* stream) {
286  remote_streams_->AddStream(stream);
287}
288
289void MockPeerConnectionImpl::CreateOffer(
290    CreateSessionDescriptionObserver* observer,
291    const MediaConstraintsInterface* constraints) {
292  DCHECK(observer);
293  created_sessiondescription_.reset(
294      dependency_factory_->CreateSessionDescription("unknown", kDummyOffer,
295                                                    NULL));
296}
297
298void MockPeerConnectionImpl::CreateAnswer(
299    CreateSessionDescriptionObserver* observer,
300    const MediaConstraintsInterface* constraints) {
301  DCHECK(observer);
302  created_sessiondescription_.reset(
303      dependency_factory_->CreateSessionDescription("unknown", kDummyAnswer,
304                                                    NULL));
305}
306
307void MockPeerConnectionImpl::SetLocalDescriptionWorker(
308    SetSessionDescriptionObserver* observer,
309    SessionDescriptionInterface* desc) {
310  desc->ToString(&description_sdp_);
311  local_desc_.reset(desc);
312}
313
314void MockPeerConnectionImpl::SetRemoteDescriptionWorker(
315    SetSessionDescriptionObserver* observer,
316    SessionDescriptionInterface* desc) {
317  desc->ToString(&description_sdp_);
318  remote_desc_.reset(desc);
319}
320
321bool MockPeerConnectionImpl::UpdateIce(
322    const IceServers& configuration,
323    const MediaConstraintsInterface* constraints) {
324  return true;
325}
326
327bool MockPeerConnectionImpl::AddIceCandidate(
328    const IceCandidateInterface* candidate) {
329  sdp_mid_ = candidate->sdp_mid();
330  sdp_mline_index_ = candidate->sdp_mline_index();
331  return candidate->ToString(&ice_sdp_);
332}
333
334}  // namespace content
335