1 // Copyright (c) 2017 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 "third_party/blink/renderer/modules/peerconnection/webrtc_set_description_observer.h"
6 
7 #include <memory>
8 #include <utility>
9 #include <vector>
10 
11 #include "base/bind.h"
12 #include "base/memory/ptr_util.h"
13 #include "base/optional.h"
14 #include "base/run_loop.h"
15 #include "base/single_thread_task_runner.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
18 #include "third_party/blink/public/web/web_heap.h"
19 #include "third_party/blink/renderer/modules/peerconnection/mock_peer_connection_dependency_factory.h"
20 #include "third_party/blink/renderer/modules/peerconnection/mock_peer_connection_impl.h"
21 #include "third_party/blink/renderer/modules/peerconnection/webrtc_media_stream_track_adapter_map.h"
22 #include "third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h"
23 #include "third_party/blink/renderer/platform/peerconnection/webrtc_util.h"
24 #include "third_party/webrtc/api/peer_connection_interface.h"
25 #include "third_party/webrtc/api/test/mock_peerconnectioninterface.h"
26 #include "third_party/webrtc/media/base/fake_media_engine.h"
27 
28 using ::testing::Return;
29 
30 namespace blink {
31 
32 class WebRtcSetDescriptionObserverForTest
33     : public WebRtcSetDescriptionObserver {
34  public:
called() const35   bool called() const { return called_; }
36 
states() const37   const WebRtcSetDescriptionObserver::States& states() const {
38     DCHECK(called_);
39     return states_;
40   }
error() const41   const webrtc::RTCError& error() const {
42     DCHECK(called_);
43     return error_;
44   }
45 
46   // WebRtcSetDescriptionObserver implementation.
OnSetDescriptionComplete(webrtc::RTCError error,WebRtcSetDescriptionObserver::States states)47   void OnSetDescriptionComplete(
48       webrtc::RTCError error,
49       WebRtcSetDescriptionObserver::States states) override {
50     called_ = true;
51     error_ = std::move(error);
52     states_ = std::move(states);
53   }
54 
55  private:
~WebRtcSetDescriptionObserverForTest()56   ~WebRtcSetDescriptionObserverForTest() override {}
57 
58   bool called_ = false;
59   webrtc::RTCError error_;
60   WebRtcSetDescriptionObserver::States states_;
61 };
62 
63 enum class ObserverHandlerType {
64   kLocal,
65   kRemote,
66 };
67 
68 // Because webrtc observer interfaces are different classes,
69 // WebRtcSetLocalDescriptionObserverHandler and
70 // WebRtcSetRemoteDescriptionObserverHandler have different class hierarchies
71 // despite implementing the same behavior. This wrapper hides these differences.
72 class ObserverHandlerWrapper {
73  public:
ObserverHandlerWrapper(ObserverHandlerType handler_type,scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner,scoped_refptr<webrtc::PeerConnectionInterface> pc,scoped_refptr<blink::WebRtcMediaStreamTrackAdapterMap> track_adapter_map,scoped_refptr<WebRtcSetDescriptionObserver> observer,bool surface_receivers_only)74   ObserverHandlerWrapper(
75       ObserverHandlerType handler_type,
76       scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
77       scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner,
78       scoped_refptr<webrtc::PeerConnectionInterface> pc,
79       scoped_refptr<blink::WebRtcMediaStreamTrackAdapterMap> track_adapter_map,
80       scoped_refptr<WebRtcSetDescriptionObserver> observer,
81       bool surface_receivers_only)
82       : signaling_task_runner_(std::move(signaling_task_runner)),
83         handler_type_(handler_type),
84         local_handler_(nullptr),
85         remote_handler_(nullptr) {
86     switch (handler_type_) {
87       case ObserverHandlerType::kLocal:
88         local_handler_ = WebRtcSetLocalDescriptionObserverHandler::Create(
89             std::move(main_task_runner), signaling_task_runner_, std::move(pc),
90             std::move(track_adapter_map), std::move(observer),
91             surface_receivers_only);
92         break;
93       case ObserverHandlerType::kRemote:
94         remote_handler_ = WebRtcSetRemoteDescriptionObserverHandler::Create(
95             std::move(main_task_runner), signaling_task_runner_, std::move(pc),
96             std::move(track_adapter_map), std::move(observer),
97             surface_receivers_only);
98         break;
99     }
100   }
101 
InvokeOnComplete(webrtc::RTCError error)102   void InvokeOnComplete(webrtc::RTCError error) {
103     switch (handler_type_) {
104       case ObserverHandlerType::kLocal:
105         if (error.ok())
106           InvokeLocalHandlerOnSuccess();
107         else
108           InvokeLocalHandlerOnFailure(std::move(error));
109         break;
110       case ObserverHandlerType::kRemote:
111         InvokeRemoteHandlerOnComplete(std::move(error));
112         break;
113     }
114   }
115 
116  private:
InvokeLocalHandlerOnSuccess()117   void InvokeLocalHandlerOnSuccess() {
118     base::RunLoop run_loop;
119     signaling_task_runner_->PostTask(
120         FROM_HERE,
121         base::BindOnce(&ObserverHandlerWrapper::
122                            InvokeLocalHandlerOnSuccessOnSignalingThread,
123                        base::Unretained(this), base::Unretained(&run_loop)));
124     run_loop.Run();
125   }
InvokeLocalHandlerOnSuccessOnSignalingThread(base::RunLoop * run_loop)126   void InvokeLocalHandlerOnSuccessOnSignalingThread(base::RunLoop* run_loop) {
127     local_handler_->OnSuccess();
128     run_loop->Quit();
129   }
130 
InvokeLocalHandlerOnFailure(webrtc::RTCError error)131   void InvokeLocalHandlerOnFailure(webrtc::RTCError error) {
132     base::RunLoop run_loop;
133     signaling_task_runner_->PostTask(
134         FROM_HERE,
135         base::BindOnce(&ObserverHandlerWrapper::
136                            InvokeLocalHandlerOnFailureOnSignalingThread,
137                        base::Unretained(this), std::move(error),
138                        base::Unretained(&run_loop)));
139     run_loop.Run();
140   }
InvokeLocalHandlerOnFailureOnSignalingThread(webrtc::RTCError error,base::RunLoop * run_loop)141   void InvokeLocalHandlerOnFailureOnSignalingThread(webrtc::RTCError error,
142                                                     base::RunLoop* run_loop) {
143     local_handler_->OnFailure(std::move(error));
144     run_loop->Quit();
145   }
146 
InvokeRemoteHandlerOnComplete(webrtc::RTCError error)147   void InvokeRemoteHandlerOnComplete(webrtc::RTCError error) {
148     base::RunLoop run_loop;
149     signaling_task_runner_->PostTask(
150         FROM_HERE,
151         base::BindOnce(&ObserverHandlerWrapper::
152                            InvokeRemoteHandlerOnCompleteOnSignalingThread,
153                        base::Unretained(this), std::move(error),
154                        base::Unretained(&run_loop)));
155     run_loop.Run();
156   }
InvokeRemoteHandlerOnCompleteOnSignalingThread(webrtc::RTCError error,base::RunLoop * run_loop)157   void InvokeRemoteHandlerOnCompleteOnSignalingThread(webrtc::RTCError error,
158                                                       base::RunLoop* run_loop) {
159     remote_handler_->OnSetRemoteDescriptionComplete(std::move(error));
160     run_loop->Quit();
161   }
162 
163   scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_;
164   ObserverHandlerType handler_type_;
165   scoped_refptr<WebRtcSetLocalDescriptionObserverHandler> local_handler_;
166   scoped_refptr<WebRtcSetRemoteDescriptionObserverHandler> remote_handler_;
167 };
168 
169 enum class StateSurfacerType {
170   kTransceivers,
171   kReceiversOnly,
172 };
173 
174 using TestVariety = std::tuple<ObserverHandlerType, StateSurfacerType>;
175 
176 struct PrintToStringTestVariety {
operator ()blink::PrintToStringTestVariety177   std::string operator()(
178       const testing::TestParamInfo<TestVariety>& info) const {
179     ObserverHandlerType handler_type = std::get<0>(info.param);
180     StateSurfacerType surfacer_type = std::get<1>(info.param);
181     std::string str;
182     switch (handler_type) {
183       case ObserverHandlerType::kLocal:
184         str += "LocalDescriptionWith";
185         break;
186       case ObserverHandlerType::kRemote:
187         str += "RemoteDescriptionWith";
188         break;
189     }
190     switch (surfacer_type) {
191       case StateSurfacerType::kTransceivers:
192         str += "TransceiverStates";
193         break;
194       case StateSurfacerType::kReceiversOnly:
195         str += "ReceiverStates";
196         break;
197     }
198     return str;
199   }
200 };
201 
202 // Using parameterization, this class is used to test both
203 // WebRtcSetLocalDescriptionObserverHandler and
204 // WebRtcSetRemoteDescriptionObserverHandler. The handlers, used for
205 // setLocalDescription() and setRemoteDescription() respectively, are virtually
206 // identical in terms of functionality but have different class hierarchies due
207 // to webrtc observer interfaces being different classes.
208 //
209 // Each handler is testable under two modes of operation: surfacing state
210 // information about transceivers (includes both senders and receivers), or only
211 // surfacing receiver state information. Unified Plan requires the former and
212 // Plan B requires the latter.
213 //
214 // Parameterization allows easily running the same tests for each handler and
215 // mode, as specified by the TestVariety.
216 class WebRtcSetDescriptionObserverHandlerTest
217     : public ::testing::TestWithParam<TestVariety> {
218  public:
WebRtcSetDescriptionObserverHandlerTest()219   WebRtcSetDescriptionObserverHandlerTest()
220       : handler_type_(std::get<0>(GetParam())),
221         surfacer_type_(std::get<1>(GetParam())) {}
222 
SetUp()223   void SetUp() override {
224     pc_ = new webrtc::MockPeerConnectionInterface;
225     dependency_factory_.reset(new blink::MockPeerConnectionDependencyFactory());
226     main_thread_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting();
227     track_adapter_map_ =
228         base::MakeRefCounted<blink::WebRtcMediaStreamTrackAdapterMap>(
229             dependency_factory_.get(), main_thread_);
230     observer_ = base::MakeRefCounted<WebRtcSetDescriptionObserverForTest>();
231     observer_handler_ = std::make_unique<ObserverHandlerWrapper>(
232         handler_type_, main_thread_,
233         dependency_factory_->GetWebRtcSignalingTaskRunner(), pc_,
234         track_adapter_map_, observer_,
235         surfacer_type_ == StateSurfacerType::kReceiversOnly);
236   }
237 
TearDown()238   void TearDown() override { blink::WebHeap::CollectAllGarbageForTesting(); }
239 
CreateLocalTrack(const std::string & id)240   blink::WebMediaStreamTrack CreateLocalTrack(const std::string& id) {
241     blink::WebMediaStreamSource web_source;
242     web_source.Initialize(
243         blink::WebString::FromUTF8(id), blink::WebMediaStreamSource::kTypeAudio,
244         blink::WebString::FromUTF8("local_audio_track"), false);
245     blink::MediaStreamAudioSource* audio_source =
246         new blink::MediaStreamAudioSource(
247             blink::scheduler::GetSingleThreadTaskRunnerForTesting(), true);
248     // Takes ownership of |audio_source|.
249     web_source.SetPlatformSource(base::WrapUnique(audio_source));
250 
251     blink::WebMediaStreamTrack web_track;
252     web_track.Initialize(web_source.Id(), web_source);
253     audio_source->ConnectToTrack(web_track);
254     return web_track;
255   }
256 
CreateTransceivers()257   void CreateTransceivers() {
258     ASSERT_EQ(StateSurfacerType::kTransceivers, surfacer_type_);
259 
260     auto web_local_track = CreateLocalTrack("local_track");
261     auto local_track_adapter =
262         track_adapter_map_->GetOrCreateLocalTrackAdapter(web_local_track);
263     scoped_refptr<webrtc::MediaStreamTrackInterface> local_track =
264         local_track_adapter->webrtc_track();
265     rtc::scoped_refptr<blink::FakeRtpSender> sender(
266         new rtc::RefCountedObject<blink::FakeRtpSender>(
267             local_track.get(), std::vector<std::string>({"local_stream"})));
268     // A requirement of WebRtcSet[Local/Remote]DescriptionObserverHandler is
269     // that local tracks have existing track adapters when the callback is
270     // invoked. In practice this would be ensured by RTCPeerConnectionHandler.
271     // Here in testing, we ensure it by adding it to |local_track_adapters_|.
272     local_track_adapters_.push_back(std::move(local_track_adapter));
273 
274     scoped_refptr<blink::MockWebRtcAudioTrack> remote_track =
275         blink::MockWebRtcAudioTrack::Create("remote_track");
276     scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
277         new rtc::RefCountedObject<blink::MockMediaStream>("remote_stream"));
278     rtc::scoped_refptr<blink::FakeRtpReceiver> receiver(
279         new rtc::RefCountedObject<blink::FakeRtpReceiver>(
280             remote_track.get(),
281             std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>(
282                 {remote_stream.get()})));
283     rtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver(
284         new rtc::RefCountedObject<blink::FakeRtpTransceiver>(
285             cricket::MEDIA_TYPE_AUDIO, sender, receiver, base::nullopt, false,
286             webrtc::RtpTransceiverDirection::kSendRecv, base::nullopt));
287     transceivers_.push_back(transceiver);
288     EXPECT_CALL(*pc_, GetTransceivers()).WillRepeatedly(Return(transceivers_));
289   }
290 
ExpectMatchingTransceivers()291   void ExpectMatchingTransceivers() {
292     ASSERT_EQ(StateSurfacerType::kTransceivers, surfacer_type_);
293     ASSERT_EQ(1u, transceivers_.size());
294 
295     auto transceiver = transceivers_[0];
296     auto sender = transceiver->sender();
297     auto receiver = transceiver->receiver();
298     EXPECT_EQ(1u, observer_->states().transceiver_states.size());
299     const blink::RtpTransceiverState& transceiver_state =
300         observer_->states().transceiver_states[0];
301     // Inspect transceiver states.
302     EXPECT_TRUE(transceiver_state.is_initialized());
303     EXPECT_EQ(transceiver.get(), transceiver_state.webrtc_transceiver());
304     EXPECT_TRUE(
305         blink::OptionalEquals(transceiver_state.mid(), transceiver->mid()));
306     EXPECT_EQ(transceiver_state.stopped(), transceiver->stopped());
307     EXPECT_TRUE(transceiver_state.direction() == transceiver->direction());
308     EXPECT_TRUE(blink::OptionalEquals(transceiver_state.current_direction(),
309                                       transceiver->current_direction()));
310     EXPECT_TRUE(blink::OptionalEquals(transceiver_state.fired_direction(),
311                                       transceiver->fired_direction()));
312     // Inspect sender states.
313     EXPECT_TRUE(transceiver_state.sender_state());
314     const blink::RtpSenderState& sender_state =
315         *transceiver_state.sender_state();
316     EXPECT_TRUE(sender_state.is_initialized());
317     EXPECT_EQ(sender.get(), sender_state.webrtc_sender());
318     EXPECT_EQ(sender->track(), sender_state.track_ref()->webrtc_track());
319     EXPECT_EQ(sender->stream_ids(), sender_state.stream_ids());
320     // Inspect receiver states.
321     EXPECT_TRUE(transceiver_state.receiver_state());
322     const blink::RtpReceiverState& receiver_state =
323         *transceiver_state.receiver_state();
324     EXPECT_TRUE(receiver_state.is_initialized());
325     EXPECT_EQ(receiver.get(), receiver_state.webrtc_receiver());
326     EXPECT_EQ(receiver->track(), receiver_state.track_ref()->webrtc_track());
327     EXPECT_EQ(receiver->stream_ids(), receiver_state.stream_ids());
328   }
329 
CreateReceivers()330   void CreateReceivers() {
331     ASSERT_EQ(StateSurfacerType::kReceiversOnly, surfacer_type_);
332 
333     scoped_refptr<blink::MockWebRtcAudioTrack> remote_track =
334         blink::MockWebRtcAudioTrack::Create("remote_track");
335     scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
336         new rtc::RefCountedObject<blink::MockMediaStream>("remote_stream"));
337     rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver(
338         new rtc::RefCountedObject<blink::FakeRtpReceiver>(
339             remote_track.get(),
340             std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>(
341                 {remote_stream.get()})));
342     receivers_.push_back(receiver);
343     EXPECT_CALL(*pc_, GetReceivers()).WillRepeatedly(Return(receivers_));
344   }
345 
ExpectMatchingReceivers()346   void ExpectMatchingReceivers() {
347     ASSERT_EQ(StateSurfacerType::kReceiversOnly, surfacer_type_);
348     ASSERT_EQ(1u, receivers_.size());
349 
350     auto receiver = receivers_[0];
351     EXPECT_EQ(1u, observer_->states().transceiver_states.size());
352     const blink::RtpTransceiverState& transceiver_state =
353         observer_->states().transceiver_states[0];
354     EXPECT_FALSE(transceiver_state.sender_state());
355     EXPECT_TRUE(transceiver_state.receiver_state());
356     const blink::RtpReceiverState& receiver_state =
357         *transceiver_state.receiver_state();
358     EXPECT_TRUE(receiver_state.is_initialized());
359     EXPECT_EQ(receiver.get(), receiver_state.webrtc_receiver());
360     EXPECT_EQ(receiver->track(), receiver_state.track_ref()->webrtc_track());
361     EXPECT_EQ(receiver->stream_ids(), receiver_state.stream_ids());
362   }
363 
364  protected:
365   scoped_refptr<webrtc::MockPeerConnectionInterface> pc_;
366   std::unique_ptr<blink::MockPeerConnectionDependencyFactory>
367       dependency_factory_;
368   scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
369   scoped_refptr<blink::WebRtcMediaStreamTrackAdapterMap> track_adapter_map_;
370   scoped_refptr<WebRtcSetDescriptionObserverForTest> observer_;
371 
372   ObserverHandlerType handler_type_;
373   StateSurfacerType surfacer_type_;
374   std::unique_ptr<ObserverHandlerWrapper> observer_handler_;
375 
376   std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>
377       transceivers_;
378   std::vector<
379       std::unique_ptr<blink::WebRtcMediaStreamTrackAdapterMap::AdapterRef>>
380       local_track_adapters_;
381   // Used instead of |transceivers_| when |surfacer_type_| is
382   // StateSurfacerType::kReceiversOnly.
383   std::vector<rtc::scoped_refptr<webrtc::RtpReceiverInterface>> receivers_;
384 };
385 
TEST_P(WebRtcSetDescriptionObserverHandlerTest,OnSuccess)386 TEST_P(WebRtcSetDescriptionObserverHandlerTest, OnSuccess) {
387   switch (surfacer_type_) {
388     case StateSurfacerType::kTransceivers:
389       CreateTransceivers();
390       break;
391     case StateSurfacerType::kReceiversOnly:
392       CreateReceivers();
393       break;
394   }
395 
396   EXPECT_CALL(*pc_, signaling_state())
397       .WillRepeatedly(Return(webrtc::PeerConnectionInterface::kStable));
398 
399   observer_handler_->InvokeOnComplete(webrtc::RTCError::OK());
400   EXPECT_TRUE(observer_->called());
401   EXPECT_TRUE(observer_->error().ok());
402 
403   EXPECT_EQ(webrtc::PeerConnectionInterface::kStable,
404             observer_->states().signaling_state);
405 
406   switch (surfacer_type_) {
407     case StateSurfacerType::kTransceivers:
408       ExpectMatchingTransceivers();
409       break;
410     case StateSurfacerType::kReceiversOnly:
411       ExpectMatchingReceivers();
412       break;
413   }
414 }
415 
TEST_P(WebRtcSetDescriptionObserverHandlerTest,OnFailure)416 TEST_P(WebRtcSetDescriptionObserverHandlerTest, OnFailure) {
417   switch (surfacer_type_) {
418     case StateSurfacerType::kTransceivers:
419       CreateTransceivers();
420       break;
421     case StateSurfacerType::kReceiversOnly:
422       CreateReceivers();
423       break;
424   }
425 
426   EXPECT_CALL(*pc_, signaling_state())
427       .WillRepeatedly(Return(webrtc::PeerConnectionInterface::kStable));
428 
429   observer_handler_->InvokeOnComplete(
430       webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER, "Oh noes!"));
431   EXPECT_TRUE(observer_->called());
432   EXPECT_FALSE(observer_->error().ok());
433   EXPECT_EQ(std::string("Oh noes!"), observer_->error().message());
434 
435   // Verify states were surfaced even though we got an error.
436   EXPECT_EQ(webrtc::PeerConnectionInterface::kStable,
437             observer_->states().signaling_state);
438 
439   switch (surfacer_type_) {
440     case StateSurfacerType::kTransceivers:
441       ExpectMatchingTransceivers();
442       break;
443     case StateSurfacerType::kReceiversOnly:
444       ExpectMatchingReceivers();
445       break;
446   }
447 }
448 
449 // Test coverage for https://crbug.com/897251. If the webrtc peer connection is
450 // implemented to invoke the callback with a delay it might already have been
451 // closed when the observer is invoked. A closed RTCPeerConnection is allowed to
452 // be garbage collected. In rare circumstances, the RTCPeerConnection,
453 // RTCPeerConnectionHandler and any local track adapters may thus have been
454 // deleted when the observer attempts to surface transceiver state information.
455 // This test insures that TransceiverStateSurfacer::Initialize() does not crash
456 // due to track adapters not existing.
TEST_P(WebRtcSetDescriptionObserverHandlerTest,ClosePeerConnectionBeforeCallback)457 TEST_P(WebRtcSetDescriptionObserverHandlerTest,
458        ClosePeerConnectionBeforeCallback) {
459   switch (surfacer_type_) {
460     case StateSurfacerType::kTransceivers:
461       CreateTransceivers();
462       break;
463     case StateSurfacerType::kReceiversOnly:
464       CreateReceivers();
465       break;
466   }
467 
468   // Simulate the peer connection having been closed and local track adapters
469   // destroyed before the observer was invoked.
470   EXPECT_CALL(*pc_, signaling_state())
471       .WillRepeatedly(Return(webrtc::PeerConnectionInterface::kClosed));
472   local_track_adapters_.clear();
473 
474   observer_handler_->InvokeOnComplete(webrtc::RTCError::OK());
475   EXPECT_TRUE(observer_->called());
476   EXPECT_TRUE(observer_->error().ok());
477 
478   EXPECT_EQ(webrtc::PeerConnectionInterface::kClosed,
479             observer_->states().signaling_state);
480 
481   EXPECT_EQ(0u, observer_->states().transceiver_states.size());
482 }
483 
484 INSTANTIATE_TEST_SUITE_P(
485     All,
486     WebRtcSetDescriptionObserverHandlerTest,
487     ::testing::Values(std::make_tuple(ObserverHandlerType::kLocal,
488                                       StateSurfacerType::kTransceivers),
489                       std::make_tuple(ObserverHandlerType::kRemote,
490                                       StateSurfacerType::kTransceivers),
491                       std::make_tuple(ObserverHandlerType::kLocal,
492                                       StateSurfacerType::kReceiversOnly),
493                       std::make_tuple(ObserverHandlerType::kRemote,
494                                       StateSurfacerType::kReceiversOnly)),
495     PrintToStringTestVariety());
496 
497 }  // namespace blink
498