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 <string>
6#include <vector>
7
8#include "base/memory/scoped_ptr.h"
9#include "base/message_loop/message_loop.h"
10#include "base/strings/utf_string_conversions.h"
11#include "base/values.h"
12#include "content/child/child_process.h"
13#include "content/renderer/media/media_stream.h"
14#include "content/renderer/media/media_stream_audio_source.h"
15#include "content/renderer/media/media_stream_source.h"
16#include "content/renderer/media/media_stream_video_track.h"
17#include "content/renderer/media/mock_media_stream_video_source.h"
18#include "content/renderer/media/mock_peer_connection_impl.h"
19#include "content/renderer/media/mock_web_rtc_peer_connection_handler_client.h"
20#include "content/renderer/media/peer_connection_tracker.h"
21#include "content/renderer/media/rtc_media_constraints.h"
22#include "content/renderer/media/rtc_peer_connection_handler.h"
23#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
24#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
25#include "content/renderer/media/webrtc_audio_capturer.h"
26#include "testing/gmock/include/gmock/gmock.h"
27#include "testing/gtest/include/gtest/gtest.h"
28#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
29#include "third_party/WebKit/public/platform/WebMediaStream.h"
30#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
31#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
32#include "third_party/WebKit/public/platform/WebRTCConfiguration.h"
33#include "third_party/WebKit/public/platform/WebRTCDTMFSenderHandler.h"
34#include "third_party/WebKit/public/platform/WebRTCDataChannelHandler.h"
35#include "third_party/WebKit/public/platform/WebRTCDataChannelInit.h"
36#include "third_party/WebKit/public/platform/WebRTCICECandidate.h"
37#include "third_party/WebKit/public/platform/WebRTCPeerConnectionHandlerClient.h"
38#include "third_party/WebKit/public/platform/WebRTCSessionDescription.h"
39#include "third_party/WebKit/public/platform/WebRTCSessionDescriptionRequest.h"
40#include "third_party/WebKit/public/platform/WebRTCStatsRequest.h"
41#include "third_party/WebKit/public/platform/WebRTCVoidRequest.h"
42#include "third_party/WebKit/public/platform/WebURL.h"
43#include "third_party/WebKit/public/web/WebHeap.h"
44#include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
45
46static const char kDummySdp[] = "dummy sdp";
47static const char kDummySdpType[] = "dummy type";
48
49using blink::WebRTCPeerConnectionHandlerClient;
50using testing::NiceMock;
51using testing::_;
52using testing::Ref;
53
54namespace content {
55
56class MockRTCStatsResponse : public LocalRTCStatsResponse {
57 public:
58  MockRTCStatsResponse()
59      : report_count_(0),
60        statistic_count_(0) {
61  }
62
63  virtual size_t addReport(blink::WebString type,
64                           blink::WebString id,
65                           double timestamp) OVERRIDE {
66    ++report_count_;
67    return report_count_;
68  }
69
70  virtual void addStatistic(size_t report,
71                            blink::WebString name, blink::WebString value)
72      OVERRIDE {
73    ++statistic_count_;
74  }
75  int report_count() const { return report_count_; }
76
77 private:
78  int report_count_;
79  int statistic_count_;
80};
81
82// Mocked wrapper for blink::WebRTCStatsRequest
83class MockRTCStatsRequest : public LocalRTCStatsRequest {
84 public:
85  MockRTCStatsRequest()
86      : has_selector_(false),
87        request_succeeded_called_(false) {}
88
89  virtual bool hasSelector() const OVERRIDE {
90    return has_selector_;
91  }
92  virtual blink::WebMediaStreamTrack component() const OVERRIDE {
93    return component_;
94  }
95  virtual scoped_refptr<LocalRTCStatsResponse> createResponse() OVERRIDE {
96    DCHECK(!response_.get());
97    response_ = new rtc::RefCountedObject<MockRTCStatsResponse>();
98    return response_;
99  }
100
101  virtual void requestSucceeded(const LocalRTCStatsResponse* response)
102      OVERRIDE {
103    EXPECT_EQ(response, response_.get());
104    request_succeeded_called_ = true;
105  }
106
107  // Function for setting whether or not a selector is available.
108  void setSelector(const blink::WebMediaStreamTrack& component) {
109    has_selector_ = true;
110    component_ = component;
111  }
112
113  // Function for inspecting the result of a stats request.
114  MockRTCStatsResponse* result() {
115    if (request_succeeded_called_) {
116      return response_.get();
117    } else {
118      return NULL;
119    }
120  }
121
122 private:
123  bool has_selector_;
124  blink::WebMediaStreamTrack component_;
125  scoped_refptr<MockRTCStatsResponse> response_;
126  bool request_succeeded_called_;
127};
128
129class MockPeerConnectionTracker : public PeerConnectionTracker {
130 public:
131  MOCK_METHOD1(UnregisterPeerConnection,
132               void(RTCPeerConnectionHandler* pc_handler));
133  // TODO(jiayl): add coverage for the following methods
134  MOCK_METHOD2(TrackCreateOffer,
135               void(RTCPeerConnectionHandler* pc_handler,
136                    const RTCMediaConstraints& constraints));
137  MOCK_METHOD2(TrackCreateAnswer,
138               void(RTCPeerConnectionHandler* pc_handler,
139                    const RTCMediaConstraints& constraints));
140  MOCK_METHOD3(TrackSetSessionDescription,
141               void(RTCPeerConnectionHandler* pc_handler,
142                    const blink::WebRTCSessionDescription& desc,
143                    Source source));
144  MOCK_METHOD3(
145      TrackUpdateIce,
146      void(RTCPeerConnectionHandler* pc_handler,
147           const webrtc::PeerConnectionInterface::RTCConfiguration& config,
148           const RTCMediaConstraints& options));
149  MOCK_METHOD4(TrackAddIceCandidate,
150               void(RTCPeerConnectionHandler* pc_handler,
151                    const blink::WebRTCICECandidate& candidate,
152                    Source source,
153                    bool succeeded));
154  MOCK_METHOD3(TrackAddStream,
155               void(RTCPeerConnectionHandler* pc_handler,
156                    const blink::WebMediaStream& stream,
157                    Source source));
158  MOCK_METHOD3(TrackRemoveStream,
159               void(RTCPeerConnectionHandler* pc_handler,
160                    const blink::WebMediaStream& stream,
161                    Source source));
162  MOCK_METHOD1(TrackOnIceComplete,
163               void(RTCPeerConnectionHandler* pc_handler));
164  MOCK_METHOD3(TrackCreateDataChannel,
165               void(RTCPeerConnectionHandler* pc_handler,
166                    const webrtc::DataChannelInterface* data_channel,
167                    Source source));
168  MOCK_METHOD1(TrackStop, void(RTCPeerConnectionHandler* pc_handler));
169  MOCK_METHOD2(TrackSignalingStateChange,
170               void(RTCPeerConnectionHandler* pc_handler,
171                    WebRTCPeerConnectionHandlerClient::SignalingState state));
172  MOCK_METHOD2(
173      TrackIceConnectionStateChange,
174      void(RTCPeerConnectionHandler* pc_handler,
175           WebRTCPeerConnectionHandlerClient::ICEConnectionState state));
176  MOCK_METHOD2(
177      TrackIceGatheringStateChange,
178      void(RTCPeerConnectionHandler* pc_handler,
179           WebRTCPeerConnectionHandlerClient::ICEGatheringState state));
180  MOCK_METHOD1(TrackOnRenegotiationNeeded,
181               void(RTCPeerConnectionHandler* pc_handler));
182  MOCK_METHOD2(TrackCreateDTMFSender,
183               void(RTCPeerConnectionHandler* pc_handler,
184                     const blink::WebMediaStreamTrack& track));
185};
186
187class RTCPeerConnectionHandlerUnderTest : public RTCPeerConnectionHandler {
188 public:
189  RTCPeerConnectionHandlerUnderTest(
190      WebRTCPeerConnectionHandlerClient* client,
191      PeerConnectionDependencyFactory* dependency_factory)
192      : RTCPeerConnectionHandler(client, dependency_factory) {
193  }
194
195  MockPeerConnectionImpl* native_peer_connection() {
196    return static_cast<MockPeerConnectionImpl*>(
197        RTCPeerConnectionHandler::native_peer_connection());
198  }
199};
200
201class RTCPeerConnectionHandlerTest : public ::testing::Test {
202 public:
203  RTCPeerConnectionHandlerTest() : mock_peer_connection_(NULL) {
204    child_process_.reset(new ChildProcess());
205  }
206
207  virtual void SetUp() {
208    mock_client_.reset(new NiceMock<MockWebRTCPeerConnectionHandlerClient>());
209    mock_dependency_factory_.reset(new MockPeerConnectionDependencyFactory());
210    pc_handler_.reset(
211        new RTCPeerConnectionHandlerUnderTest(mock_client_.get(),
212                                              mock_dependency_factory_.get()));
213    mock_tracker_.reset(new NiceMock<MockPeerConnectionTracker>());
214    blink::WebRTCConfiguration config;
215    blink::WebMediaConstraints constraints;
216    EXPECT_TRUE(pc_handler_->InitializeForTest(config, constraints,
217                                               mock_tracker_.get()));
218
219    mock_peer_connection_ = pc_handler_->native_peer_connection();
220    ASSERT_TRUE(mock_peer_connection_);
221  }
222
223  virtual void TearDown() {
224    pc_handler_.reset();
225    mock_tracker_.reset();
226    mock_dependency_factory_.reset();
227    mock_client_.reset();
228    blink::WebHeap::collectAllGarbageForTesting();
229  }
230
231  // Creates a WebKit local MediaStream.
232  blink::WebMediaStream CreateLocalMediaStream(
233      const std::string& stream_label) {
234    std::string video_track_label("video-label");
235    std::string audio_track_label("audio-label");
236
237    blink::WebMediaStreamSource audio_source;
238    audio_source.initialize(blink::WebString::fromUTF8(audio_track_label),
239                            blink::WebMediaStreamSource::TypeAudio,
240                            blink::WebString::fromUTF8("audio_track"));
241    audio_source.setExtraData(new MediaStreamAudioSource());
242    blink::WebMediaStreamSource video_source;
243    video_source.initialize(blink::WebString::fromUTF8(video_track_label),
244                            blink::WebMediaStreamSource::TypeVideo,
245                            blink::WebString::fromUTF8("video_track"));
246    MockMediaStreamVideoSource* native_video_source =
247        new MockMediaStreamVideoSource(false);
248    video_source.setExtraData(native_video_source);
249
250    blink::WebVector<blink::WebMediaStreamTrack> audio_tracks(
251        static_cast<size_t>(1));
252    audio_tracks[0].initialize(audio_source.id(), audio_source);
253    audio_tracks[0].setExtraData(
254        new MediaStreamTrack(
255            WebRtcLocalAudioTrackAdapter::Create(audio_track_label,
256                                                 NULL),
257                                                 true));
258    blink::WebVector<blink::WebMediaStreamTrack> video_tracks(
259        static_cast<size_t>(1));
260    blink::WebMediaConstraints constraints;
261    constraints.initialize();
262    video_tracks[0] = MediaStreamVideoTrack::CreateVideoTrack(
263        native_video_source, constraints,
264        MediaStreamVideoSource::ConstraintsCallback(), true);
265
266    blink::WebMediaStream local_stream;
267    local_stream.initialize(base::UTF8ToUTF16(stream_label), audio_tracks,
268                            video_tracks);
269    local_stream.setExtraData(
270        new MediaStream(local_stream));
271    return local_stream;
272  }
273
274  // Creates a remote MediaStream and adds it to the mocked native
275  // peer connection.
276  scoped_refptr<webrtc::MediaStreamInterface>
277  AddRemoteMockMediaStream(const std::string& stream_label,
278                           const std::string& video_track_label,
279                           const std::string& audio_track_label) {
280    scoped_refptr<webrtc::MediaStreamInterface> stream(
281        mock_dependency_factory_->CreateLocalMediaStream(stream_label));
282    if (!video_track_label.empty()) {
283      webrtc::VideoSourceInterface* source = NULL;
284      scoped_refptr<webrtc::VideoTrackInterface> video_track(
285          mock_dependency_factory_->CreateLocalVideoTrack(
286              video_track_label, source));
287      stream->AddTrack(video_track.get());
288    }
289    if (!audio_track_label.empty()) {
290      scoped_refptr<WebRtcAudioCapturer> capturer;
291      scoped_refptr<webrtc::AudioTrackInterface> audio_track(
292          WebRtcLocalAudioTrackAdapter::Create(audio_track_label, NULL));
293      stream->AddTrack(audio_track.get());
294    }
295    mock_peer_connection_->AddRemoteStream(stream.get());
296    return stream;
297  }
298
299  base::MessageLoop message_loop_;
300  scoped_ptr<ChildProcess> child_process_;
301  scoped_ptr<MockWebRTCPeerConnectionHandlerClient> mock_client_;
302  scoped_ptr<MockPeerConnectionDependencyFactory> mock_dependency_factory_;
303  scoped_ptr<NiceMock<MockPeerConnectionTracker> > mock_tracker_;
304  scoped_ptr<RTCPeerConnectionHandlerUnderTest> pc_handler_;
305
306  // Weak reference to the mocked native peer connection implementation.
307  MockPeerConnectionImpl* mock_peer_connection_;
308};
309
310TEST_F(RTCPeerConnectionHandlerTest, Destruct) {
311  EXPECT_CALL(*mock_tracker_.get(), UnregisterPeerConnection(pc_handler_.get()))
312      .Times(1);
313  pc_handler_.reset(NULL);
314}
315
316TEST_F(RTCPeerConnectionHandlerTest, CreateOffer) {
317  blink::WebRTCSessionDescriptionRequest request;
318  blink::WebMediaConstraints options;
319  EXPECT_CALL(*mock_tracker_.get(), TrackCreateOffer(pc_handler_.get(), _));
320
321  // TODO(perkj): Can blink::WebRTCSessionDescriptionRequest be changed so
322  // the |reqest| requestSucceeded can be tested? Currently the |request| object
323  // can not be initialized from a unit test.
324  EXPECT_FALSE(mock_peer_connection_->created_session_description() != NULL);
325  pc_handler_->createOffer(request, options);
326  EXPECT_TRUE(mock_peer_connection_->created_session_description() != NULL);
327}
328
329TEST_F(RTCPeerConnectionHandlerTest, CreateAnswer) {
330  blink::WebRTCSessionDescriptionRequest request;
331  blink::WebMediaConstraints options;
332  EXPECT_CALL(*mock_tracker_.get(), TrackCreateAnswer(pc_handler_.get(), _));
333  // TODO(perkj): Can blink::WebRTCSessionDescriptionRequest be changed so
334  // the |reqest| requestSucceeded can be tested? Currently the |request| object
335  // can not be initialized from a unit test.
336  EXPECT_FALSE(mock_peer_connection_->created_session_description() != NULL);
337  pc_handler_->createAnswer(request, options);
338  EXPECT_TRUE(mock_peer_connection_->created_session_description() != NULL);
339}
340
341TEST_F(RTCPeerConnectionHandlerTest, setLocalDescription) {
342  blink::WebRTCVoidRequest request;
343  blink::WebRTCSessionDescription description;
344  description.initialize(kDummySdpType, kDummySdp);
345  // PeerConnectionTracker::TrackSetSessionDescription is expected to be called
346  // before |mock_peer_connection| is called.
347  testing::InSequence sequence;
348  EXPECT_CALL(*mock_tracker_.get(),
349              TrackSetSessionDescription(pc_handler_.get(), Ref(description),
350                                         PeerConnectionTracker::SOURCE_LOCAL));
351  EXPECT_CALL(*mock_peer_connection_, SetLocalDescription(_, _));
352
353  pc_handler_->setLocalDescription(request, description);
354  EXPECT_EQ(description.type(), pc_handler_->localDescription().type());
355  EXPECT_EQ(description.sdp(), pc_handler_->localDescription().sdp());
356
357  std::string sdp_string;
358  ASSERT_TRUE(mock_peer_connection_->local_description() != NULL);
359  EXPECT_EQ(kDummySdpType, mock_peer_connection_->local_description()->type());
360  mock_peer_connection_->local_description()->ToString(&sdp_string);
361  EXPECT_EQ(kDummySdp, sdp_string);
362}
363
364TEST_F(RTCPeerConnectionHandlerTest, setRemoteDescription) {
365  blink::WebRTCVoidRequest request;
366  blink::WebRTCSessionDescription description;
367  description.initialize(kDummySdpType, kDummySdp);
368
369  // PeerConnectionTracker::TrackSetSessionDescription is expected to be called
370  // before |mock_peer_connection| is called.
371  testing::InSequence sequence;
372  EXPECT_CALL(*mock_tracker_.get(),
373              TrackSetSessionDescription(pc_handler_.get(), Ref(description),
374                                         PeerConnectionTracker::SOURCE_REMOTE));
375  EXPECT_CALL(*mock_peer_connection_, SetRemoteDescription(_, _));
376
377  pc_handler_->setRemoteDescription(request, description);
378  EXPECT_EQ(description.type(), pc_handler_->remoteDescription().type());
379  EXPECT_EQ(description.sdp(), pc_handler_->remoteDescription().sdp());
380
381  std::string sdp_string;
382  ASSERT_TRUE(mock_peer_connection_->remote_description() != NULL);
383  EXPECT_EQ(kDummySdpType, mock_peer_connection_->remote_description()->type());
384  mock_peer_connection_->remote_description()->ToString(&sdp_string);
385  EXPECT_EQ(kDummySdp, sdp_string);
386}
387
388TEST_F(RTCPeerConnectionHandlerTest, updateICE) {
389  blink::WebRTCConfiguration config;
390  blink::WebMediaConstraints constraints;
391
392  EXPECT_CALL(*mock_tracker_.get(), TrackUpdateIce(pc_handler_.get(), _, _));
393  // TODO(perkj): Test that the parameters in |config| can be translated when a
394  // WebRTCConfiguration can be constructed. It's WebKit class and can't be
395  // initialized from a test.
396  EXPECT_TRUE(pc_handler_->updateICE(config, constraints));
397}
398
399TEST_F(RTCPeerConnectionHandlerTest, addICECandidate) {
400  blink::WebRTCICECandidate candidate;
401  candidate.initialize(kDummySdp, "sdpMid", 1);
402
403  EXPECT_CALL(*mock_tracker_.get(),
404              TrackAddIceCandidate(pc_handler_.get(),
405                                   testing::Ref(candidate),
406                                   PeerConnectionTracker::SOURCE_REMOTE,
407                                   true));
408  EXPECT_TRUE(pc_handler_->addICECandidate(candidate));
409  EXPECT_EQ(kDummySdp, mock_peer_connection_->ice_sdp());
410  EXPECT_EQ(1, mock_peer_connection_->sdp_mline_index());
411  EXPECT_EQ("sdpMid", mock_peer_connection_->sdp_mid());
412}
413
414TEST_F(RTCPeerConnectionHandlerTest, addAndRemoveStream) {
415  std::string stream_label = "local_stream";
416  blink::WebMediaStream local_stream(
417      CreateLocalMediaStream(stream_label));
418  blink::WebMediaConstraints constraints;
419
420  EXPECT_CALL(*mock_tracker_.get(),
421              TrackAddStream(pc_handler_.get(),
422                             testing::Ref(local_stream),
423                             PeerConnectionTracker::SOURCE_LOCAL));
424  EXPECT_CALL(*mock_tracker_.get(),
425              TrackRemoveStream(pc_handler_.get(),
426                                testing::Ref(local_stream),
427                                PeerConnectionTracker::SOURCE_LOCAL));
428  EXPECT_TRUE(pc_handler_->addStream(local_stream, constraints));
429  EXPECT_EQ(stream_label, mock_peer_connection_->stream_label());
430  EXPECT_EQ(1u,
431      mock_peer_connection_->local_streams()->at(0)->GetAudioTracks().size());
432  EXPECT_EQ(1u,
433      mock_peer_connection_->local_streams()->at(0)->GetVideoTracks().size());
434
435  EXPECT_FALSE(pc_handler_->addStream(local_stream, constraints));
436
437  pc_handler_->removeStream(local_stream);
438  EXPECT_EQ(0u, mock_peer_connection_->local_streams()->count());
439}
440
441TEST_F(RTCPeerConnectionHandlerTest, addStreamWithStoppedAudioAndVideoTrack) {
442  std::string stream_label = "local_stream";
443  blink::WebMediaStream local_stream(
444      CreateLocalMediaStream(stream_label));
445  blink::WebMediaConstraints constraints;
446
447  blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
448  local_stream.audioTracks(audio_tracks);
449  MediaStreamAudioSource* native_audio_source =
450      static_cast<MediaStreamAudioSource*>(
451          audio_tracks[0].source().extraData());
452  native_audio_source->StopSource();
453
454  blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
455  local_stream.videoTracks(video_tracks);
456  MediaStreamVideoSource* native_video_source =
457      static_cast<MediaStreamVideoSource*>(
458          video_tracks[0].source().extraData());
459  native_video_source->StopSource();
460
461  EXPECT_TRUE(pc_handler_->addStream(local_stream, constraints));
462  EXPECT_EQ(stream_label, mock_peer_connection_->stream_label());
463  EXPECT_EQ(
464      1u,
465      mock_peer_connection_->local_streams()->at(0)->GetAudioTracks().size());
466  EXPECT_EQ(
467      1u,
468      mock_peer_connection_->local_streams()->at(0)->GetVideoTracks().size());
469}
470
471TEST_F(RTCPeerConnectionHandlerTest, GetStatsNoSelector) {
472  scoped_refptr<MockRTCStatsRequest> request(
473      new rtc::RefCountedObject<MockRTCStatsRequest>());
474  pc_handler_->getStats(request.get());
475  // Note that callback gets executed synchronously by mock.
476  ASSERT_TRUE(request->result());
477  EXPECT_LT(1, request->result()->report_count());
478}
479
480TEST_F(RTCPeerConnectionHandlerTest, GetStatsAfterClose) {
481  scoped_refptr<MockRTCStatsRequest> request(
482      new rtc::RefCountedObject<MockRTCStatsRequest>());
483  pc_handler_->stop();
484  pc_handler_->getStats(request.get());
485  // Note that callback gets executed synchronously by mock.
486  ASSERT_TRUE(request->result());
487  EXPECT_LT(1, request->result()->report_count());
488}
489
490TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithLocalSelector) {
491  blink::WebMediaStream local_stream(
492      CreateLocalMediaStream("local_stream"));
493  blink::WebMediaConstraints constraints;
494  pc_handler_->addStream(local_stream, constraints);
495  blink::WebVector<blink::WebMediaStreamTrack> tracks;
496  local_stream.audioTracks(tracks);
497  ASSERT_LE(1ul, tracks.size());
498
499  scoped_refptr<MockRTCStatsRequest> request(
500      new rtc::RefCountedObject<MockRTCStatsRequest>());
501  request->setSelector(tracks[0]);
502  pc_handler_->getStats(request.get());
503  EXPECT_EQ(1, request->result()->report_count());
504}
505
506TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithRemoteSelector) {
507  scoped_refptr<webrtc::MediaStreamInterface> stream(
508      AddRemoteMockMediaStream("remote_stream", "video", "audio"));
509  pc_handler_->OnAddStream(stream.get());
510  const blink::WebMediaStream& remote_stream = mock_client_->remote_stream();
511
512  blink::WebVector<blink::WebMediaStreamTrack> tracks;
513  remote_stream.audioTracks(tracks);
514  ASSERT_LE(1ul, tracks.size());
515
516  scoped_refptr<MockRTCStatsRequest> request(
517      new rtc::RefCountedObject<MockRTCStatsRequest>());
518  request->setSelector(tracks[0]);
519  pc_handler_->getStats(request.get());
520  EXPECT_EQ(1, request->result()->report_count());
521}
522
523TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithBadSelector) {
524  // The setup is the same as GetStatsWithLocalSelector, but the stream is not
525  // added to the PeerConnection.
526  blink::WebMediaStream local_stream(
527      CreateLocalMediaStream("local_stream_2"));
528  blink::WebMediaConstraints constraints;
529  blink::WebVector<blink::WebMediaStreamTrack> tracks;
530
531  local_stream.audioTracks(tracks);
532  blink::WebMediaStreamTrack component = tracks[0];
533  mock_peer_connection_->SetGetStatsResult(false);
534
535  scoped_refptr<MockRTCStatsRequest> request(
536      new rtc::RefCountedObject<MockRTCStatsRequest>());
537  request->setSelector(component);
538  pc_handler_->getStats(request.get());
539  EXPECT_EQ(0, request->result()->report_count());
540}
541
542TEST_F(RTCPeerConnectionHandlerTest, OnSignalingChange) {
543  testing::InSequence sequence;
544
545  webrtc::PeerConnectionInterface::SignalingState new_state =
546      webrtc::PeerConnectionInterface::kHaveRemoteOffer;
547  EXPECT_CALL(*mock_tracker_.get(), TrackSignalingStateChange(
548      pc_handler_.get(),
549      WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemoteOffer));
550  EXPECT_CALL(*mock_client_.get(), didChangeSignalingState(
551      WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemoteOffer));
552  pc_handler_->OnSignalingChange(new_state);
553
554  new_state = webrtc::PeerConnectionInterface::kHaveLocalPrAnswer;
555  EXPECT_CALL(*mock_tracker_.get(), TrackSignalingStateChange(
556      pc_handler_.get(),
557      WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalPrAnswer));
558  EXPECT_CALL(*mock_client_.get(), didChangeSignalingState(
559      WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalPrAnswer));
560  pc_handler_->OnSignalingChange(new_state);
561
562  new_state = webrtc::PeerConnectionInterface::kHaveLocalOffer;
563  EXPECT_CALL(*mock_tracker_.get(), TrackSignalingStateChange(
564      pc_handler_.get(),
565      WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalOffer));
566  EXPECT_CALL(*mock_client_.get(), didChangeSignalingState(
567      WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalOffer));
568  pc_handler_->OnSignalingChange(new_state);
569
570  new_state = webrtc::PeerConnectionInterface::kHaveRemotePrAnswer;
571  EXPECT_CALL(*mock_tracker_.get(), TrackSignalingStateChange(
572      pc_handler_.get(),
573      WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemotePrAnswer));
574  EXPECT_CALL(*mock_client_.get(), didChangeSignalingState(
575      WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemotePrAnswer));
576  pc_handler_->OnSignalingChange(new_state);
577
578  new_state = webrtc::PeerConnectionInterface::kClosed;
579  EXPECT_CALL(*mock_tracker_.get(), TrackSignalingStateChange(
580      pc_handler_.get(),
581      WebRTCPeerConnectionHandlerClient::SignalingStateClosed));
582  EXPECT_CALL(*mock_client_.get(), didChangeSignalingState(
583      WebRTCPeerConnectionHandlerClient::SignalingStateClosed));
584  pc_handler_->OnSignalingChange(new_state);
585}
586
587TEST_F(RTCPeerConnectionHandlerTest, OnIceConnectionChange) {
588  testing::InSequence sequence;
589
590  webrtc::PeerConnectionInterface::IceConnectionState new_state =
591      webrtc::PeerConnectionInterface::kIceConnectionNew;
592  EXPECT_CALL(*mock_tracker_.get(), TrackIceConnectionStateChange(
593      pc_handler_.get(),
594      WebRTCPeerConnectionHandlerClient::ICEConnectionStateStarting));
595  EXPECT_CALL(*mock_client_.get(), didChangeICEConnectionState(
596      WebRTCPeerConnectionHandlerClient::ICEConnectionStateStarting));
597  pc_handler_->OnIceConnectionChange(new_state);
598
599  new_state = webrtc::PeerConnectionInterface::kIceConnectionChecking;
600  EXPECT_CALL(*mock_tracker_.get(), TrackIceConnectionStateChange(
601      pc_handler_.get(),
602      WebRTCPeerConnectionHandlerClient::ICEConnectionStateChecking));
603  EXPECT_CALL(*mock_client_.get(), didChangeICEConnectionState(
604      WebRTCPeerConnectionHandlerClient::ICEConnectionStateChecking));
605  pc_handler_->OnIceConnectionChange(new_state);
606
607  new_state = webrtc::PeerConnectionInterface::kIceConnectionConnected;
608  EXPECT_CALL(*mock_tracker_.get(), TrackIceConnectionStateChange(
609      pc_handler_.get(),
610      WebRTCPeerConnectionHandlerClient::ICEConnectionStateConnected));
611  EXPECT_CALL(*mock_client_.get(), didChangeICEConnectionState(
612      WebRTCPeerConnectionHandlerClient::ICEConnectionStateConnected));
613  pc_handler_->OnIceConnectionChange(new_state);
614
615  new_state = webrtc::PeerConnectionInterface::kIceConnectionCompleted;
616  EXPECT_CALL(*mock_tracker_.get(), TrackIceConnectionStateChange(
617      pc_handler_.get(),
618      WebRTCPeerConnectionHandlerClient::ICEConnectionStateCompleted));
619  EXPECT_CALL(*mock_client_.get(), didChangeICEConnectionState(
620      WebRTCPeerConnectionHandlerClient::ICEConnectionStateCompleted));
621  pc_handler_->OnIceConnectionChange(new_state);
622
623  new_state = webrtc::PeerConnectionInterface::kIceConnectionFailed;
624  EXPECT_CALL(*mock_tracker_.get(), TrackIceConnectionStateChange(
625      pc_handler_.get(),
626      WebRTCPeerConnectionHandlerClient::ICEConnectionStateFailed));
627  EXPECT_CALL(*mock_client_.get(), didChangeICEConnectionState(
628      WebRTCPeerConnectionHandlerClient::ICEConnectionStateFailed));
629  pc_handler_->OnIceConnectionChange(new_state);
630
631  new_state = webrtc::PeerConnectionInterface::kIceConnectionDisconnected;
632  EXPECT_CALL(*mock_tracker_.get(), TrackIceConnectionStateChange(
633      pc_handler_.get(),
634      WebRTCPeerConnectionHandlerClient::ICEConnectionStateDisconnected));
635  EXPECT_CALL(*mock_client_.get(), didChangeICEConnectionState(
636      WebRTCPeerConnectionHandlerClient::ICEConnectionStateDisconnected));
637  pc_handler_->OnIceConnectionChange(new_state);
638
639  new_state = webrtc::PeerConnectionInterface::kIceConnectionClosed;
640  EXPECT_CALL(*mock_tracker_.get(), TrackIceConnectionStateChange(
641      pc_handler_.get(),
642      WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed));
643  EXPECT_CALL(*mock_client_.get(), didChangeICEConnectionState(
644      WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed));
645  pc_handler_->OnIceConnectionChange(new_state);
646}
647
648TEST_F(RTCPeerConnectionHandlerTest, OnIceGatheringChange) {
649  testing::InSequence sequence;
650  EXPECT_CALL(*mock_tracker_.get(), TrackIceGatheringStateChange(
651      pc_handler_.get(),
652      WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew));
653  EXPECT_CALL(*mock_client_.get(), didChangeICEGatheringState(
654      WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew));
655  EXPECT_CALL(*mock_tracker_.get(), TrackIceGatheringStateChange(
656      pc_handler_.get(),
657      WebRTCPeerConnectionHandlerClient::ICEGatheringStateGathering));
658  EXPECT_CALL(*mock_client_.get(), didChangeICEGatheringState(
659      WebRTCPeerConnectionHandlerClient::ICEGatheringStateGathering));
660  EXPECT_CALL(*mock_tracker_.get(), TrackIceGatheringStateChange(
661      pc_handler_.get(),
662      WebRTCPeerConnectionHandlerClient::ICEGatheringStateComplete));
663  EXPECT_CALL(*mock_client_.get(), didChangeICEGatheringState(
664      WebRTCPeerConnectionHandlerClient::ICEGatheringStateComplete));
665
666  webrtc::PeerConnectionInterface::IceGatheringState new_state =
667        webrtc::PeerConnectionInterface::kIceGatheringNew;
668  pc_handler_->OnIceGatheringChange(new_state);
669
670  new_state = webrtc::PeerConnectionInterface::kIceGatheringGathering;
671  pc_handler_->OnIceGatheringChange(new_state);
672
673  new_state = webrtc::PeerConnectionInterface::kIceGatheringComplete;
674  pc_handler_->OnIceGatheringChange(new_state);
675
676  // Check NULL candidate after ice gathering is completed.
677  EXPECT_EQ("", mock_client_->candidate_mid());
678  EXPECT_EQ(-1, mock_client_->candidate_mlineindex());
679  EXPECT_EQ("", mock_client_->candidate_sdp());
680}
681
682TEST_F(RTCPeerConnectionHandlerTest, OnAddAndOnRemoveStream) {
683  std::string remote_stream_label("remote_stream");
684  scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
685      AddRemoteMockMediaStream(remote_stream_label, "video", "audio"));
686
687  testing::InSequence sequence;
688  EXPECT_CALL(*mock_tracker_.get(), TrackAddStream(
689      pc_handler_.get(),
690      testing::Property(&blink::WebMediaStream::id,
691                        base::UTF8ToUTF16(remote_stream_label)),
692      PeerConnectionTracker::SOURCE_REMOTE));
693  EXPECT_CALL(*mock_client_.get(), didAddRemoteStream(
694      testing::Property(&blink::WebMediaStream::id,
695                        base::UTF8ToUTF16(remote_stream_label))));
696
697  EXPECT_CALL(*mock_tracker_.get(), TrackRemoveStream(
698      pc_handler_.get(),
699      testing::Property(&blink::WebMediaStream::id,
700                        base::UTF8ToUTF16(remote_stream_label)),
701      PeerConnectionTracker::SOURCE_REMOTE));
702  EXPECT_CALL(*mock_client_.get(), didRemoveRemoteStream(
703      testing::Property(&blink::WebMediaStream::id,
704                        base::UTF8ToUTF16(remote_stream_label))));
705
706  pc_handler_->OnAddStream(remote_stream.get());
707  pc_handler_->OnRemoveStream(remote_stream.get());
708}
709
710// This test that WebKit is notified about remote track state changes.
711TEST_F(RTCPeerConnectionHandlerTest, RemoteTrackState) {
712  std::string remote_stream_label("remote_stream");
713  scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
714      AddRemoteMockMediaStream(remote_stream_label, "video", "audio"));
715
716  testing::InSequence sequence;
717  EXPECT_CALL(*mock_client_.get(), didAddRemoteStream(
718      testing::Property(&blink::WebMediaStream::id,
719                        base::UTF8ToUTF16(remote_stream_label))));
720  pc_handler_->OnAddStream(remote_stream.get());
721  const blink::WebMediaStream& webkit_stream = mock_client_->remote_stream();
722
723  blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
724  webkit_stream.audioTracks(audio_tracks);
725  EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive,
726            audio_tracks[0].source().readyState());
727
728  blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
729    webkit_stream.videoTracks(video_tracks);
730  EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive,
731            video_tracks[0].source().readyState());
732
733  remote_stream->GetAudioTracks()[0]->set_state(
734      webrtc::MediaStreamTrackInterface::kEnded);
735  EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded,
736            audio_tracks[0].source().readyState());
737
738  remote_stream->GetVideoTracks()[0]->set_state(
739      webrtc::MediaStreamTrackInterface::kEnded);
740  EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded,
741            video_tracks[0].source().readyState());
742}
743
744TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddAudioTrackFromRemoteStream) {
745  std::string remote_stream_label("remote_stream");
746  scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
747      AddRemoteMockMediaStream(remote_stream_label, "video", "audio"));
748
749  EXPECT_CALL(*mock_client_.get(), didAddRemoteStream(
750      testing::Property(&blink::WebMediaStream::id,
751                        base::UTF8ToUTF16(remote_stream_label))));
752  pc_handler_->OnAddStream(remote_stream.get());
753  const blink::WebMediaStream& webkit_stream = mock_client_->remote_stream();
754
755  {
756    // Test in a small scope so that  |audio_tracks| don't hold on to destroyed
757    // source later.
758    blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
759    webkit_stream.audioTracks(audio_tracks);
760    EXPECT_EQ(1u, audio_tracks.size());
761  }
762
763  // Remove the Webrtc audio track from the Webrtc MediaStream.
764  scoped_refptr<webrtc::AudioTrackInterface> webrtc_track =
765      remote_stream->GetAudioTracks()[0].get();
766  remote_stream->RemoveTrack(webrtc_track.get());
767
768  {
769    blink::WebVector<blink::WebMediaStreamTrack> modified_audio_tracks1;
770    webkit_stream.audioTracks(modified_audio_tracks1);
771    EXPECT_EQ(0u, modified_audio_tracks1.size());
772  }
773
774  blink::WebHeap::collectGarbageForTesting();
775
776  // Add the WebRtc audio track again.
777  remote_stream->AddTrack(webrtc_track.get());
778  blink::WebVector<blink::WebMediaStreamTrack> modified_audio_tracks2;
779  webkit_stream.audioTracks(modified_audio_tracks2);
780  EXPECT_EQ(1u, modified_audio_tracks2.size());
781}
782
783TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddVideoTrackFromRemoteStream) {
784  std::string remote_stream_label("remote_stream");
785  scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
786      AddRemoteMockMediaStream(remote_stream_label, "video", "video"));
787
788  EXPECT_CALL(*mock_client_.get(), didAddRemoteStream(
789      testing::Property(&blink::WebMediaStream::id,
790                        base::UTF8ToUTF16(remote_stream_label))));
791  pc_handler_->OnAddStream(remote_stream.get());
792  const blink::WebMediaStream& webkit_stream = mock_client_->remote_stream();
793
794  {
795    // Test in a small scope so that  |video_tracks| don't hold on to destroyed
796    // source later.
797    blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
798    webkit_stream.videoTracks(video_tracks);
799    EXPECT_EQ(1u, video_tracks.size());
800  }
801
802  // Remove the Webrtc video track from the Webrtc MediaStream.
803  scoped_refptr<webrtc::VideoTrackInterface> webrtc_track =
804      remote_stream->GetVideoTracks()[0].get();
805  remote_stream->RemoveTrack(webrtc_track.get());
806  {
807    blink::WebVector<blink::WebMediaStreamTrack> modified_video_tracks1;
808    webkit_stream.videoTracks(modified_video_tracks1);
809    EXPECT_EQ(0u, modified_video_tracks1.size());
810  }
811
812  blink::WebHeap::collectGarbageForTesting();
813
814  // Add the WebRtc video track again.
815  remote_stream->AddTrack(webrtc_track.get());
816  blink::WebVector<blink::WebMediaStreamTrack> modified_video_tracks2;
817  webkit_stream.videoTracks(modified_video_tracks2);
818  EXPECT_EQ(1u, modified_video_tracks2.size());
819}
820
821TEST_F(RTCPeerConnectionHandlerTest, OnIceCandidate) {
822  testing::InSequence sequence;
823  EXPECT_CALL(*mock_tracker_.get(),
824              TrackAddIceCandidate(pc_handler_.get(), _,
825                                   PeerConnectionTracker::SOURCE_LOCAL, true));
826  EXPECT_CALL(*mock_client_.get(), didGenerateICECandidate(_));
827
828  scoped_ptr<webrtc::IceCandidateInterface> native_candidate(
829      mock_dependency_factory_->CreateIceCandidate("sdpMid", 1, kDummySdp));
830  pc_handler_->OnIceCandidate(native_candidate.get());
831  EXPECT_EQ("sdpMid", mock_client_->candidate_mid());
832  EXPECT_EQ(1, mock_client_->candidate_mlineindex());
833  EXPECT_EQ(kDummySdp, mock_client_->candidate_sdp());
834}
835
836TEST_F(RTCPeerConnectionHandlerTest, OnRenegotiationNeeded) {
837  testing::InSequence sequence;
838  EXPECT_CALL(*mock_tracker_.get(),
839              TrackOnRenegotiationNeeded(pc_handler_.get()));
840  EXPECT_CALL(*mock_client_.get(), negotiationNeeded());
841  pc_handler_->OnRenegotiationNeeded();
842}
843
844TEST_F(RTCPeerConnectionHandlerTest, CreateDataChannel) {
845  blink::WebString label = "d1";
846  EXPECT_CALL(*mock_tracker_.get(),
847              TrackCreateDataChannel(pc_handler_.get(),
848                                     testing::NotNull(),
849                                     PeerConnectionTracker::SOURCE_LOCAL));
850  scoped_ptr<blink::WebRTCDataChannelHandler> channel(
851      pc_handler_->createDataChannel("d1", blink::WebRTCDataChannelInit()));
852  EXPECT_TRUE(channel.get() != NULL);
853  EXPECT_EQ(label, channel->label());
854}
855
856TEST_F(RTCPeerConnectionHandlerTest, CreateDtmfSender) {
857  std::string stream_label = "local_stream";
858  blink::WebMediaStream local_stream(CreateLocalMediaStream(stream_label));
859  blink::WebMediaConstraints constraints;
860  pc_handler_->addStream(local_stream, constraints);
861
862  blink::WebVector<blink::WebMediaStreamTrack> tracks;
863  local_stream.videoTracks(tracks);
864
865  ASSERT_LE(1ul, tracks.size());
866  EXPECT_FALSE(pc_handler_->createDTMFSender(tracks[0]));
867
868  local_stream.audioTracks(tracks);
869  ASSERT_LE(1ul, tracks.size());
870
871  EXPECT_CALL(*mock_tracker_.get(),
872              TrackCreateDTMFSender(pc_handler_.get(),
873                                    testing::Ref(tracks[0])));
874
875  scoped_ptr<blink::WebRTCDTMFSenderHandler> sender(
876      pc_handler_->createDTMFSender(tracks[0]));
877  EXPECT_TRUE(sender.get());
878}
879
880}  // namespace content
881