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 <queue> 7 8#include "base/bind.h" 9#include "base/callback_helpers.h" 10#include "base/message_loop/message_loop.h" 11#include "base/run_loop.h" 12#include "content/browser/browser_thread_impl.h" 13#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h" 14#include "content/browser/renderer_host/media/media_stream_manager.h" 15#include "content/browser/renderer_host/media/media_stream_ui_proxy.h" 16#include "content/common/media/media_stream_messages.h" 17#include "content/common/media/media_stream_options.h" 18#include "content/public/browser/media_device_id.h" 19#include "content/public/test/mock_resource_context.h" 20#include "content/public/test/test_browser_context.h" 21#include "content/public/test/test_browser_thread_bundle.h" 22#include "content/test/test_content_browser_client.h" 23#include "content/test/test_content_client.h" 24#include "ipc/ipc_message_macros.h" 25#include "media/audio/mock_audio_manager.h" 26#include "media/video/capture/fake_video_capture_device.h" 27#include "net/url_request/url_request_context.h" 28#include "testing/gmock/include/gmock/gmock.h" 29#include "testing/gtest/include/gtest/gtest.h" 30 31using ::testing::_; 32using ::testing::DeleteArg; 33using ::testing::DoAll; 34using ::testing::Return; 35using ::testing::SaveArg; 36 37const int kProcessId = 5; 38const int kRenderId = 6; 39const int kPageRequestId = 7; 40 41namespace content { 42 43class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost, 44 public TestContentBrowserClient { 45 public: 46 MockMediaStreamDispatcherHost( 47 const ResourceContext::SaltCallback salt_callback, 48 const scoped_refptr<base::MessageLoopProxy>& message_loop, 49 MediaStreamManager* manager) 50 : MediaStreamDispatcherHost(kProcessId, salt_callback, manager), 51 message_loop_(message_loop) {} 52 53 // A list of mock methods. 54 MOCK_METHOD4(OnStreamGenerated, 55 void(int routing_id, int request_id, int audio_array_size, 56 int video_array_size)); 57 MOCK_METHOD2(OnStreamGenerationFailed, void(int routing_id, int request_id)); 58 MOCK_METHOD1(OnDeviceStopped, void(int routing_id)); 59 MOCK_METHOD2(OnDeviceOpened, void(int routing_id, int request_id)); 60 61 // Accessor to private functions. 62 void OnGenerateStream(int render_view_id, 63 int page_request_id, 64 const StreamOptions& components, 65 const GURL& security_origin, 66 const base::Closure& quit_closure) { 67 quit_closures_.push(quit_closure); 68 MediaStreamDispatcherHost::OnGenerateStream( 69 render_view_id, page_request_id, components, security_origin); 70 } 71 72 void OnStopStreamDevice(int render_view_id, 73 const std::string& device_id) { 74 MediaStreamDispatcherHost::OnStopStreamDevice(render_view_id, device_id); 75 } 76 77 void OnOpenDevice(int render_view_id, 78 int page_request_id, 79 const std::string& device_id, 80 MediaStreamType type, 81 const GURL& security_origin, 82 const base::Closure& quit_closure) { 83 quit_closures_.push(quit_closure); 84 MediaStreamDispatcherHost::OnOpenDevice( 85 render_view_id, page_request_id, device_id, type, security_origin); 86 } 87 88 void OnEnumerateDevices(int render_view_id, 89 int page_request_id, 90 MediaStreamType type, 91 const GURL& security_origin, 92 const base::Closure& quit_closure) { 93 quit_closures_.push(quit_closure); 94 MediaStreamDispatcherHost::OnEnumerateDevices( 95 render_view_id, page_request_id, type, security_origin); 96 } 97 98 std::string label_; 99 StreamDeviceInfoArray audio_devices_; 100 StreamDeviceInfoArray video_devices_; 101 StreamDeviceInfo opened_device_; 102 StreamDeviceInfoArray enumerated_devices_; 103 104 private: 105 virtual ~MockMediaStreamDispatcherHost() {} 106 107 // This method is used to dispatch IPC messages to the renderer. We intercept 108 // these messages here and dispatch to our mock methods to verify the 109 // conversation between this object and the renderer. 110 virtual bool Send(IPC::Message* message) OVERRIDE { 111 CHECK(message); 112 113 // In this method we dispatch the messages to the according handlers as if 114 // we are the renderer. 115 bool handled = true; 116 IPC_BEGIN_MESSAGE_MAP(MockMediaStreamDispatcherHost, *message) 117 IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerated, OnStreamGenerated) 118 IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerationFailed, 119 OnStreamGenerationFailed) 120 IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceStopped, OnDeviceStopped) 121 IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpened, OnDeviceOpened) 122 IPC_MESSAGE_HANDLER(MediaStreamMsg_DevicesEnumerated, 123 OnDevicesEnumerated) 124 IPC_MESSAGE_UNHANDLED(handled = false) 125 IPC_END_MESSAGE_MAP() 126 EXPECT_TRUE(handled); 127 128 delete message; 129 return true; 130 } 131 132 // These handler methods do minimal things and delegate to the mock methods. 133 void OnStreamGenerated( 134 const IPC::Message& msg, 135 int request_id, 136 std::string label, 137 StreamDeviceInfoArray audio_device_list, 138 StreamDeviceInfoArray video_device_list) { 139 OnStreamGenerated(msg.routing_id(), request_id, audio_device_list.size(), 140 video_device_list.size()); 141 // Notify that the event have occurred. 142 base::Closure quit_closure = quit_closures_.front(); 143 quit_closures_.pop(); 144 message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure)); 145 146 label_ = label; 147 audio_devices_ = audio_device_list; 148 video_devices_ = video_device_list; 149 } 150 151 void OnStreamGenerationFailed(const IPC::Message& msg, int request_id) { 152 OnStreamGenerationFailed(msg.routing_id(), request_id); 153 if (!quit_closures_.empty()) { 154 base::Closure quit_closure = quit_closures_.front(); 155 quit_closures_.pop(); 156 message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure)); 157 } 158 159 label_= ""; 160 } 161 162 void OnDeviceStopped(const IPC::Message& msg, 163 const std::string& label, 164 const content::StreamDeviceInfo& device) { 165 if (IsVideoMediaType(device.device.type)) 166 EXPECT_TRUE(StreamDeviceInfo::IsEqual(device, video_devices_[0])); 167 if (IsAudioMediaType(device.device.type)) 168 EXPECT_TRUE(StreamDeviceInfo::IsEqual(device, audio_devices_[0])); 169 170 OnDeviceStopped(msg.routing_id()); 171 } 172 173 void OnDeviceOpened(const IPC::Message& msg, 174 int request_id, 175 const std::string& label, 176 const StreamDeviceInfo& device) { 177 base::Closure quit_closure = quit_closures_.front(); 178 quit_closures_.pop(); 179 message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure)); 180 label_ = label; 181 opened_device_ = device; 182 } 183 184 void OnDevicesEnumerated(const IPC::Message& msg, 185 int request_id, 186 const StreamDeviceInfoArray& devices) { 187 base::Closure quit_closure = quit_closures_.front(); 188 quit_closures_.pop(); 189 message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure)); 190 enumerated_devices_ = devices; 191 } 192 193 scoped_refptr<base::MessageLoopProxy> message_loop_; 194 195 std::queue<base::Closure> quit_closures_; 196}; 197 198class MockMediaStreamUIProxy : public FakeMediaStreamUIProxy { 199 public: 200 MOCK_METHOD1(OnStarted, void(const base::Closure& stop)); 201}; 202 203class MediaStreamDispatcherHostTest : public testing::Test { 204 public: 205 MediaStreamDispatcherHostTest() 206 : old_browser_client_(NULL), 207 thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), 208 origin_("https://test.com") { 209 audio_manager_.reset( 210 new media::MockAudioManager(base::MessageLoopProxy::current())); 211 // Create our own MediaStreamManager. 212 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); 213 // Make sure we use fake devices to avoid long delays. 214 media_stream_manager_->UseFakeDevice(); 215 216 host_ = new MockMediaStreamDispatcherHost( 217 browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), 218 base::MessageLoopProxy::current(), 219 media_stream_manager_.get()); 220 221 // Use the fake content client and browser. 222 content_client_.reset(new TestContentClient()); 223 SetContentClient(content_client_.get()); 224 old_browser_client_ = SetBrowserClientForTesting(host_.get()); 225 } 226 227 virtual ~MediaStreamDispatcherHostTest() { 228 } 229 230 virtual void SetUp() OVERRIDE { 231 media::FakeVideoCaptureDevice::GetDeviceNames(&physical_video_devices_); 232 ASSERT_GT(physical_video_devices_.size(), 0u); 233 234 audio_manager_->GetAudioInputDeviceNames(&physical_audio_devices_); 235 ASSERT_GT(physical_audio_devices_.size(), 0u); 236 } 237 238 virtual void TearDown() OVERRIDE { 239 host_->OnChannelClosing(); 240 } 241 242 protected: 243 virtual void SetupFakeUI(bool expect_started) { 244 scoped_ptr<MockMediaStreamUIProxy> stream_ui(new MockMediaStreamUIProxy()); 245 if (expect_started) { 246 EXPECT_CALL(*stream_ui, OnStarted(_)); 247 } 248 media_stream_manager_->UseFakeUI( 249 stream_ui.PassAs<FakeMediaStreamUIProxy>()); 250 } 251 252 void GenerateStreamAndWaitForResult(int render_view_id, 253 int page_request_id, 254 const StreamOptions& options) { 255 base::RunLoop run_loop; 256 int expected_audio_array_size = 257 (options.audio_requested && 258 physical_audio_devices_.size() > 0) ? 1 : 0; 259 int expected_video_array_size = 260 (options.video_requested && 261 physical_video_devices_.size() > 0) ? 1 : 0; 262 EXPECT_CALL(*host_.get(), OnStreamGenerated(render_view_id, page_request_id, 263 expected_audio_array_size, 264 expected_video_array_size)); 265 host_->OnGenerateStream(render_view_id, page_request_id, options, origin_, 266 run_loop.QuitClosure()); 267 run_loop.Run(); 268 EXPECT_FALSE(DoesContainRawIds(host_->audio_devices_)); 269 EXPECT_FALSE(DoesContainRawIds(host_->video_devices_)); 270 EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->audio_devices_, origin_)); 271 EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->video_devices_, origin_)); 272 } 273 274 void GenerateStreamAndWaitForFailure(int render_view_id, 275 int page_request_id, 276 const StreamOptions& options) { 277 base::RunLoop run_loop; 278 EXPECT_CALL(*host_.get(), 279 OnStreamGenerationFailed(render_view_id, page_request_id)); 280 host_->OnGenerateStream(render_view_id, page_request_id, options, origin_, 281 run_loop.QuitClosure()); 282 run_loop.Run(); 283 } 284 285 void OpenVideoDeviceAndWaitForResult(int render_view_id, 286 int page_request_id, 287 const std::string& device_id) { 288 base::RunLoop run_loop; 289 host_->OnOpenDevice(render_view_id, page_request_id, device_id, 290 MEDIA_DEVICE_VIDEO_CAPTURE, origin_, 291 run_loop.QuitClosure()); 292 run_loop.Run(); 293 EXPECT_FALSE(DoesContainRawIds(host_->video_devices_)); 294 EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->video_devices_, origin_)); 295 } 296 297 void EnumerateDevicesAndWaitForResult(int render_view_id, 298 int page_request_id, 299 MediaStreamType type) { 300 base::RunLoop run_loop; 301 host_->OnEnumerateDevices(render_view_id, page_request_id, type, origin_, 302 run_loop.QuitClosure()); 303 run_loop.Run(); 304 ASSERT_FALSE(host_->enumerated_devices_.empty()); 305 EXPECT_FALSE(DoesContainRawIds(host_->enumerated_devices_)); 306 EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->enumerated_devices_, origin_)); 307 } 308 309 bool DoesContainRawIds(const StreamDeviceInfoArray& devices) { 310 for (size_t i = 0; i < devices.size(); ++i) { 311 media::AudioDeviceNames::const_iterator audio_it = 312 physical_audio_devices_.begin(); 313 for (; audio_it != physical_audio_devices_.end(); ++audio_it) { 314 if (audio_it->unique_id == devices[i].device.id) 315 return true; 316 } 317 media::VideoCaptureDevice::Names::const_iterator video_it = 318 physical_video_devices_.begin(); 319 for (; video_it != physical_video_devices_.end(); ++video_it) { 320 if (video_it->id() == devices[i].device.id) 321 return true; 322 } 323 } 324 return false; 325 } 326 327 bool DoesEveryDeviceMapToRawId(const StreamDeviceInfoArray& devices, 328 const GURL& origin) { 329 for (size_t i = 0; i < devices.size(); ++i) { 330 bool found_match = false; 331 media::AudioDeviceNames::const_iterator audio_it = 332 physical_audio_devices_.begin(); 333 for (; audio_it != physical_audio_devices_.end(); ++audio_it) { 334 if (content::DoesMediaDeviceIDMatchHMAC( 335 browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), 336 origin, 337 devices[i].device.id, 338 audio_it->unique_id)) { 339 EXPECT_FALSE(found_match); 340 found_match = true; 341 } 342 } 343 media::VideoCaptureDevice::Names::const_iterator video_it = 344 physical_video_devices_.begin(); 345 for (; video_it != physical_video_devices_.end(); ++video_it) { 346 if (content::DoesMediaDeviceIDMatchHMAC( 347 browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), 348 origin, 349 devices[i].device.id, 350 video_it->id())) { 351 EXPECT_FALSE(found_match); 352 found_match = true; 353 } 354 } 355 if (!found_match) 356 return false; 357 } 358 return true; 359 } 360 361 void AddSourceIdConstraint(const std::string& source_id, 362 StreamOptions::Constraints* constraints) { 363 constraints->push_back(StreamOptions::Constraint(kMediaStreamSourceInfoId, 364 source_id)); 365 } 366 367 scoped_refptr<MockMediaStreamDispatcherHost> host_; 368 scoped_ptr<media::AudioManager> audio_manager_; 369 scoped_ptr<MediaStreamManager> media_stream_manager_; 370 ContentBrowserClient* old_browser_client_; 371 scoped_ptr<ContentClient> content_client_; 372 content::TestBrowserThreadBundle thread_bundle_; 373 content::TestBrowserContext browser_context_; 374 media::AudioDeviceNames physical_audio_devices_; 375 media::VideoCaptureDevice::Names physical_video_devices_; 376 GURL origin_; 377}; 378 379TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithVideoOnly) { 380 StreamOptions options(false, true); 381 382 SetupFakeUI(true); 383 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 384 385 EXPECT_EQ(host_->audio_devices_.size(), 0u); 386 EXPECT_EQ(host_->video_devices_.size(), 1u); 387} 388 389TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithAudioOnly) { 390 StreamOptions options(true, false); 391 392 SetupFakeUI(true); 393 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 394 395 EXPECT_EQ(host_->audio_devices_.size(), 1u); 396 EXPECT_EQ(host_->video_devices_.size(), 0u); 397} 398 399TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithNothing) { 400 StreamOptions options(false, false); 401 402 GenerateStreamAndWaitForFailure(kRenderId, kPageRequestId, options); 403} 404 405TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithAudioAndVideo) { 406 StreamOptions options(true, true); 407 408 SetupFakeUI(true); 409 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 410 411 EXPECT_EQ(host_->audio_devices_.size(), 1u); 412 EXPECT_EQ(host_->video_devices_.size(), 1u); 413} 414 415// This test generates two streams with video only using the same render view 416// id. The same capture device with the same device and session id is expected 417// to be used. 418TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsFromSameRenderId) { 419 StreamOptions options(false, true); 420 421 // Generate first stream. 422 SetupFakeUI(true); 423 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 424 425 // Check the latest generated stream. 426 EXPECT_EQ(host_->audio_devices_.size(), 0u); 427 EXPECT_EQ(host_->video_devices_.size(), 1u); 428 const std::string label1 = host_->label_; 429 const std::string device_id1 = host_->video_devices_.front().device.id; 430 const int session_id1 = host_->video_devices_.front().session_id; 431 432 // Generate second stream. 433 SetupFakeUI(true); 434 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId + 1, options); 435 436 // Check the latest generated stream. 437 EXPECT_EQ(host_->audio_devices_.size(), 0u); 438 EXPECT_EQ(host_->video_devices_.size(), 1u); 439 const std::string label2 = host_->label_; 440 const std::string device_id2 = host_->video_devices_.front().device.id; 441 int session_id2 = host_->video_devices_.front().session_id; 442 EXPECT_EQ(device_id1, device_id2); 443 EXPECT_EQ(session_id1, session_id2); 444 EXPECT_NE(label1, label2); 445} 446 447TEST_F(MediaStreamDispatcherHostTest, 448 GenerateStreamAndOpenDeviceFromSameRenderId) { 449 StreamOptions options(false, true); 450 451 // Generate first stream. 452 SetupFakeUI(true); 453 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 454 455 EXPECT_EQ(host_->audio_devices_.size(), 0u); 456 EXPECT_EQ(host_->video_devices_.size(), 1u); 457 const std::string label1 = host_->label_; 458 const std::string device_id1 = host_->video_devices_.front().device.id; 459 const int session_id1 = host_->video_devices_.front().session_id; 460 461 // Generate second stream. 462 OpenVideoDeviceAndWaitForResult(kRenderId, kPageRequestId, device_id1); 463 464 const std::string device_id2 = host_->opened_device_.device.id; 465 const int session_id2 = host_->opened_device_.session_id; 466 const std::string label2 = host_->label_; 467 468 EXPECT_EQ(device_id1, device_id2); 469 EXPECT_NE(session_id1, session_id2); 470 EXPECT_NE(label1, label2); 471} 472 473 474// This test generates two streams with video only using two separate render 475// view ids. The same device id but different session ids are expected. 476TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsDifferentRenderId) { 477 StreamOptions options(false, true); 478 479 // Generate first stream. 480 SetupFakeUI(true); 481 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 482 483 // Check the latest generated stream. 484 EXPECT_EQ(host_->audio_devices_.size(), 0u); 485 EXPECT_EQ(host_->video_devices_.size(), 1u); 486 const std::string label1 = host_->label_; 487 const std::string device_id1 = host_->video_devices_.front().device.id; 488 const int session_id1 = host_->video_devices_.front().session_id; 489 490 // Generate second stream from another render view. 491 SetupFakeUI(true); 492 GenerateStreamAndWaitForResult(kRenderId+1, kPageRequestId + 1, options); 493 494 // Check the latest generated stream. 495 EXPECT_EQ(host_->audio_devices_.size(), 0u); 496 EXPECT_EQ(host_->video_devices_.size(), 1u); 497 const std::string label2 = host_->label_; 498 const std::string device_id2 = host_->video_devices_.front().device.id; 499 const int session_id2 = host_->video_devices_.front().session_id; 500 EXPECT_EQ(device_id1, device_id2); 501 EXPECT_NE(session_id1, session_id2); 502 EXPECT_NE(label1, label2); 503} 504 505// This test request two streams with video only without waiting for the first 506// stream to be generated before requesting the second. 507// The same device id and session ids are expected. 508TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithoutWaiting) { 509 StreamOptions options(false, true); 510 511 // Generate first stream. 512 SetupFakeUI(true); 513 EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1)); 514 515 // Generate second stream. 516 EXPECT_CALL(*host_.get(), 517 OnStreamGenerated(kRenderId, kPageRequestId + 1, 0, 1)); 518 519 base::RunLoop run_loop1; 520 base::RunLoop run_loop2; 521 host_->OnGenerateStream(kRenderId, kPageRequestId, options, origin_, 522 run_loop1.QuitClosure()); 523 host_->OnGenerateStream(kRenderId, kPageRequestId + 1, options, origin_, 524 run_loop2.QuitClosure()); 525 526 run_loop1.Run(); 527 run_loop2.Run(); 528} 529 530// Test that we can generate streams where a mandatory sourceId is specified in 531// the request. 532TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithMandatorySourceId) { 533 ASSERT_GE(physical_audio_devices_.size(), 1u); 534 ASSERT_GE(physical_video_devices_.size(), 1u); 535 536 media::AudioDeviceNames::const_iterator audio_it = 537 physical_audio_devices_.begin(); 538 for (; audio_it != physical_audio_devices_.end(); ++audio_it) { 539 std::string source_id = content::GetHMACForMediaDeviceID( 540 browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), 541 origin_, 542 audio_it->unique_id); 543 ASSERT_FALSE(source_id.empty()); 544 StreamOptions options(true, true); 545 AddSourceIdConstraint(source_id, &options.mandatory_audio); 546 547 SetupFakeUI(true); 548 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 549 EXPECT_EQ(host_->audio_devices_[0].device.id, source_id); 550 } 551 552 media::VideoCaptureDevice::Names::const_iterator video_it = 553 physical_video_devices_.begin(); 554 for (; video_it != physical_video_devices_.end(); ++video_it) { 555 std::string source_id = content::GetHMACForMediaDeviceID( 556 browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), 557 origin_, 558 video_it->id()); 559 ASSERT_FALSE(source_id.empty()); 560 StreamOptions options(true, true); 561 AddSourceIdConstraint(source_id, &options.mandatory_video); 562 563 SetupFakeUI(true); 564 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 565 EXPECT_EQ(host_->video_devices_[0].device.id, source_id); 566 } 567} 568 569// Test that we can generate streams where a optional sourceId is specified in 570// the request. 571TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithOptionalSourceId) { 572 ASSERT_GE(physical_audio_devices_.size(), 1u); 573 ASSERT_GE(physical_video_devices_.size(), 1u); 574 575 media::AudioDeviceNames::const_iterator audio_it = 576 physical_audio_devices_.begin(); 577 for (; audio_it != physical_audio_devices_.end(); ++audio_it) { 578 std::string source_id = content::GetHMACForMediaDeviceID( 579 browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), 580 origin_, 581 audio_it->unique_id); 582 ASSERT_FALSE(source_id.empty()); 583 StreamOptions options(true, true); 584 AddSourceIdConstraint(source_id, &options.optional_audio); 585 586 SetupFakeUI(true); 587 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 588 EXPECT_EQ(host_->audio_devices_[0].device.id, source_id); 589 } 590 591 media::VideoCaptureDevice::Names::const_iterator video_it = 592 physical_video_devices_.begin(); 593 for (; video_it != physical_video_devices_.end(); ++video_it) { 594 std::string source_id = content::GetHMACForMediaDeviceID( 595 browser_context_.GetResourceContext()->GetMediaDeviceIDSalt(), 596 origin_, 597 video_it->id()); 598 ASSERT_FALSE(source_id.empty()); 599 StreamOptions options(true, true); 600 AddSourceIdConstraint(source_id, &options.optional_video); 601 602 SetupFakeUI(true); 603 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 604 EXPECT_EQ(host_->video_devices_[0].device.id, source_id); 605 } 606} 607 608// Test that generating a stream with an invalid mandatory video source id fail. 609TEST_F(MediaStreamDispatcherHostTest, 610 GenerateStreamsWithInvalidMandatoryVideoSourceId) { 611 StreamOptions options(true, true); 612 AddSourceIdConstraint("invalid source id", &options.mandatory_video); 613 614 GenerateStreamAndWaitForFailure(kRenderId, kPageRequestId, options); 615} 616 617// Test that generating a stream with an invalid mandatory audio source id fail. 618TEST_F(MediaStreamDispatcherHostTest, 619 GenerateStreamsWithInvalidMandatoryAudioSourceId) { 620 StreamOptions options(true, true); 621 AddSourceIdConstraint("invalid source id", &options.mandatory_audio); 622 623 GenerateStreamAndWaitForFailure(kRenderId, kPageRequestId, options); 624} 625 626// Test that generating a stream with an invalid optional video source id 627// succeed. 628TEST_F(MediaStreamDispatcherHostTest, 629 GenerateStreamsWithInvalidOptionalVideoSourceId) { 630 StreamOptions options(true, true); 631 AddSourceIdConstraint("invalid source id", &options.optional_video); 632 633 SetupFakeUI(true); 634 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 635} 636 637// Test that generating a stream with an invalid optional audio source id 638// succeed. 639TEST_F(MediaStreamDispatcherHostTest, 640 GenerateStreamsWithInvalidOptionalAudioSourceId) { 641 StreamOptions options(true, true); 642 AddSourceIdConstraint("invalid source id", &options.optional_audio); 643 644 SetupFakeUI(true); 645 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 646} 647 648TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsNoAvailableVideoDevice) { 649 size_t number_of_fake_devices = physical_video_devices_.size(); 650 media::FakeVideoCaptureDevice::SetNumberOfFakeDevices(0); 651 media::FakeVideoCaptureDevice::GetDeviceNames(&physical_video_devices_); 652 StreamOptions options(true, true); 653 654 SetupFakeUI(true); 655 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 656 EXPECT_TRUE(host_->video_devices_.empty()); 657 658 // Reset the number of fake devices for next test. 659 media::FakeVideoCaptureDevice::SetNumberOfFakeDevices(number_of_fake_devices); 660} 661 662// Test that if a OnStopStreamDevice message is received for a device that has 663// been opened in a MediaStream and by pepper, the device is only stopped for 664// the MediaStream. 665TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStream) { 666 StreamOptions options(false, true); 667 668 SetupFakeUI(true); 669 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 670 671 std::string stream_request_label = host_->label_; 672 StreamDeviceInfo video_device_info = host_->video_devices_.front(); 673 ASSERT_EQ(1u, media_stream_manager_->GetDevicesOpenedByRequest( 674 stream_request_label).size()); 675 676 // Open the same device by Pepper. 677 OpenVideoDeviceAndWaitForResult(kRenderId, kPageRequestId, 678 video_device_info.device.id); 679 std::string open_device_request_label = host_->label_; 680 681 // Stop the device in the MediaStream. 682 host_->OnStopStreamDevice(kRenderId, video_device_info.device.id); 683 684 EXPECT_EQ(0u, media_stream_manager_->GetDevicesOpenedByRequest( 685 stream_request_label).size()); 686 EXPECT_EQ(1u, media_stream_manager_->GetDevicesOpenedByRequest( 687 open_device_request_label).size()); 688} 689 690TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStreamAndRestart) { 691 StreamOptions options(true, true); 692 693 SetupFakeUI(true); 694 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 695 696 std::string request_label1 = host_->label_; 697 StreamDeviceInfo video_device_info = host_->video_devices_.front(); 698 // Expect that 1 audio and 1 video device has been opened. 699 EXPECT_EQ(2u, media_stream_manager_->GetDevicesOpenedByRequest( 700 request_label1).size()); 701 702 host_->OnStopStreamDevice(kRenderId, video_device_info.device.id); 703 EXPECT_EQ(1u, media_stream_manager_->GetDevicesOpenedByRequest( 704 request_label1).size()); 705 706 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 707 std::string request_label2 = host_->label_; 708 709 StreamDeviceInfoArray request1_devices = 710 media_stream_manager_->GetDevicesOpenedByRequest(request_label1); 711 StreamDeviceInfoArray request2_devices = 712 media_stream_manager_->GetDevicesOpenedByRequest(request_label2); 713 714 ASSERT_EQ(1u, request1_devices.size()); 715 ASSERT_EQ(2u, request2_devices.size()); 716 717 // Test that the same audio device has been opened in both streams. 718 EXPECT_TRUE(StreamDeviceInfo::IsEqual(request1_devices[0], 719 request2_devices[0]) || 720 StreamDeviceInfo::IsEqual(request1_devices[0], 721 request2_devices[1])); 722} 723 724TEST_F(MediaStreamDispatcherHostTest, CancelPendingStreamsOnChannelClosing) { 725 StreamOptions options(false, true); 726 727 base::RunLoop run_loop; 728 729 // Create multiple GenerateStream requests. 730 size_t streams = 5; 731 for (size_t i = 1; i <= streams; ++i) { 732 host_->OnGenerateStream(kRenderId, kPageRequestId + i, options, origin_, 733 run_loop.QuitClosure()); 734 } 735 736 // Calling OnChannelClosing() to cancel all the pending requests. 737 host_->OnChannelClosing(); 738 run_loop.RunUntilIdle(); 739} 740 741TEST_F(MediaStreamDispatcherHostTest, StopGeneratedStreamsOnChannelClosing) { 742 StreamOptions options(false, true); 743 744 // Create first group of streams. 745 size_t generated_streams = 3; 746 for (size_t i = 0; i < generated_streams; ++i) { 747 SetupFakeUI(true); 748 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId + i, options); 749 } 750 751 // Calling OnChannelClosing() to cancel all the pending/generated streams. 752 host_->OnChannelClosing(); 753 base::RunLoop().RunUntilIdle(); 754} 755 756TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) { 757 StreamOptions options(false, true); 758 759 base::Closure close_callback; 760 scoped_ptr<MockMediaStreamUIProxy> stream_ui(new MockMediaStreamUIProxy()); 761 EXPECT_CALL(*stream_ui, OnStarted(_)) 762 .WillOnce(SaveArg<0>(&close_callback)); 763 media_stream_manager_->UseFakeUI(stream_ui.PassAs<FakeMediaStreamUIProxy>()); 764 765 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 766 767 EXPECT_EQ(host_->audio_devices_.size(), 0u); 768 EXPECT_EQ(host_->video_devices_.size(), 1u); 769 770 ASSERT_FALSE(close_callback.is_null()); 771 EXPECT_CALL(*host_.get(), OnDeviceStopped(kRenderId)); 772 close_callback.Run(); 773 base::RunLoop().RunUntilIdle(); 774} 775 776// Test that the dispatcher is notified if a video device that is in use is 777// being unplugged. 778TEST_F(MediaStreamDispatcherHostTest, VideoDeviceUnplugged) { 779 size_t number_of_fake_devices = physical_video_devices_.size(); 780 StreamOptions options(true, true); 781 SetupFakeUI(true); 782 GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options); 783 EXPECT_EQ(host_->audio_devices_.size(), 1u); 784 EXPECT_EQ(host_->video_devices_.size(), 1u); 785 786 media::FakeVideoCaptureDevice::SetNumberOfFakeDevices(0); 787 788 base::RunLoop run_loop; 789 EXPECT_CALL(*host_.get(), OnDeviceStopped(kRenderId)) 790 .WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); 791 media_stream_manager_->OnDevicesChanged( 792 base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE); 793 794 run_loop.Run(); 795 796 media::FakeVideoCaptureDevice::SetNumberOfFakeDevices(number_of_fake_devices); 797} 798 799TEST_F(MediaStreamDispatcherHostTest, EnumerateAudioDevices) { 800 EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId, 801 MEDIA_DEVICE_AUDIO_CAPTURE); 802} 803 804TEST_F(MediaStreamDispatcherHostTest, EnumerateVideoDevices) { 805 EnumerateDevicesAndWaitForResult(kRenderId, kPageRequestId, 806 MEDIA_DEVICE_VIDEO_CAPTURE); 807} 808 809}; // namespace content 810