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