| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/renderer_host/media/audio_renderer_host.h" | 5 #include "content/browser/renderer_host/media/audio_renderer_host.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 }; | 120 }; |
| 121 | 121 |
| 122 } // namespace | 122 } // namespace |
| 123 | 123 |
| 124 class MockAudioRendererHost : public AudioRendererHost { | 124 class MockAudioRendererHost : public AudioRendererHost { |
| 125 public: | 125 public: |
| 126 MockAudioRendererHost(base::RunLoop* auth_run_loop, | 126 MockAudioRendererHost(base::RunLoop* auth_run_loop, |
| 127 int render_process_id, | 127 int render_process_id, |
| 128 media::AudioManager* audio_manager, | 128 media::AudioManager* audio_manager, |
| 129 AudioMirroringManager* mirroring_manager, | 129 AudioMirroringManager* mirroring_manager, |
| 130 MediaInternals* media_internals, | |
| 131 MediaStreamManager* media_stream_manager, | 130 MediaStreamManager* media_stream_manager, |
| 132 const std::string& salt) | 131 const std::string& salt) |
| 133 : AudioRendererHost(render_process_id, | 132 : AudioRendererHost(render_process_id, |
| 134 audio_manager, | 133 audio_manager, |
| 135 mirroring_manager, | 134 mirroring_manager, |
| 136 media_internals, | |
| 137 media_stream_manager, | 135 media_stream_manager, |
| 138 salt), | 136 salt), |
| 139 shared_memory_length_(0), | 137 shared_memory_length_(0), |
| 140 auth_run_loop_(auth_run_loop) { | 138 auth_run_loop_(auth_run_loop) { |
| 141 set_render_frame_id_validate_function_for_testing(&ValidateRenderFrameId); | 139 set_render_frame_id_validate_function_for_testing(&ValidateRenderFrameId); |
| 142 } | 140 } |
| 143 | 141 |
| 144 // A list of mock methods. | 142 // A list of mock methods. |
| 145 MOCK_METHOD4(OnDeviceAuthorized, | 143 MOCK_METHOD4(OnDeviceAuthorized, |
| 146 void(int stream_id, | 144 void(int stream_id, |
| 147 media::OutputDeviceStatus device_status, | 145 media::OutputDeviceStatus device_status, |
| 148 const media::AudioParameters& output_params, | 146 const media::AudioParameters& output_params, |
| 149 const std::string& matched_device_id)); | 147 const std::string& matched_device_id)); |
| 150 MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length)); | 148 MOCK_METHOD2(WasNotifiedOfCreation, void(int stream_id, int length)); |
| 151 MOCK_METHOD1(OnStreamError, void(int stream_id)); | 149 MOCK_METHOD1(WasNotifiedOfError, void(int stream_id)); |
| 152 | 150 |
| 153 void ShutdownForBadMessage() override { bad_msg_count++; } | 151 void ShutdownForBadMessage() override { bad_msg_count++; } |
| 154 | 152 |
| 155 int bad_msg_count = 0; | 153 int bad_msg_count = 0; |
| 156 | 154 |
| 157 private: | 155 private: |
| 158 virtual ~MockAudioRendererHost() { | 156 virtual ~MockAudioRendererHost() { |
| 159 // Make sure all audio streams have been deleted. | 157 // Make sure all audio streams have been deleted. |
| 160 EXPECT_TRUE(audio_entries_.empty()); | 158 EXPECT_TRUE(delegates_.empty()); |
| 161 } | 159 } |
| 162 | 160 |
| 163 // This method is used to dispatch IPC messages to the renderer. We intercept | 161 // This method is used to dispatch IPC messages to the renderer. We intercept |
| 164 // these messages here and dispatch to our mock methods to verify the | 162 // these messages here and dispatch to our mock methods to verify the |
| 165 // conversation between this object and the renderer. | 163 // conversation between this object and the renderer. |
| 166 // Note: this means that file descriptors won't be duplicated, | 164 // Note: this means that file descriptors won't be duplicated, |
| 167 // leading to double-close errors from SyncSocket. | 165 // leading to double-close errors from SyncSocket. |
| 168 // See crbug.com/647659. | 166 // See crbug.com/647659. |
| 169 bool Send(IPC::Message* message) override { | 167 bool Send(IPC::Message* message) override { |
| 170 CHECK(message); | 168 CHECK(message); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 CHECK(shared_memory_->Map(length)); | 206 CHECK(shared_memory_->Map(length)); |
| 209 CHECK(shared_memory_->memory()); | 207 CHECK(shared_memory_->memory()); |
| 210 shared_memory_length_ = length; | 208 shared_memory_length_ = length; |
| 211 | 209 |
| 212 // Create the SyncSocket using the handle. | 210 // Create the SyncSocket using the handle. |
| 213 base::SyncSocket::Handle sync_socket_handle = | 211 base::SyncSocket::Handle sync_socket_handle = |
| 214 base::SyncSocket::UnwrapHandle(socket_descriptor); | 212 base::SyncSocket::UnwrapHandle(socket_descriptor); |
| 215 sync_socket_.reset(new base::SyncSocket(sync_socket_handle)); | 213 sync_socket_.reset(new base::SyncSocket(sync_socket_handle)); |
| 216 | 214 |
| 217 // And then delegate the call to the mock method. | 215 // And then delegate the call to the mock method. |
| 218 OnStreamCreated(stream_id, length); | 216 WasNotifiedOfCreation(stream_id, length); |
| 219 } | 217 } |
| 220 | 218 |
| 221 void OnNotifyStreamError(int stream_id) { OnStreamError(stream_id); } | 219 void OnNotifyStreamError(int stream_id) { WasNotifiedOfError(stream_id); } |
| 222 | 220 |
| 223 std::unique_ptr<base::SharedMemory> shared_memory_; | 221 std::unique_ptr<base::SharedMemory> shared_memory_; |
| 224 std::unique_ptr<base::SyncSocket> sync_socket_; | 222 std::unique_ptr<base::SyncSocket> sync_socket_; |
| 225 uint32_t shared_memory_length_; | 223 uint32_t shared_memory_length_; |
| 226 base::RunLoop* auth_run_loop_; // Used to wait for authorization. | 224 base::RunLoop* auth_run_loop_; // Used to wait for authorization. |
| 227 | 225 |
| 228 DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost); | 226 DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost); |
| 229 }; | 227 }; |
| 230 | 228 |
| 231 class AudioRendererHostTest : public testing::Test { | 229 class AudioRendererHostTest : public testing::Test { |
| 232 public: | 230 public: |
| 233 AudioRendererHostTest() | 231 AudioRendererHostTest() |
| 234 : log_factory(base::MakeUnique<media::FakeAudioLogFactory>()), | 232 : log_factory(base::MakeUnique<media::FakeAudioLogFactory>()), |
| 235 audio_manager_(base::MakeUnique<FakeAudioManagerWithAssociations>( | 233 audio_manager_(base::MakeUnique<FakeAudioManagerWithAssociations>( |
| 236 base::ThreadTaskRunnerHandle::Get(), | 234 base::ThreadTaskRunnerHandle::Get(), |
| 237 log_factory.get())), | 235 log_factory.get())), |
| 238 render_process_host_(&browser_context_, &auth_run_loop_) { | 236 render_process_host_(&browser_context_, &auth_run_loop_) { |
| 239 base::CommandLine::ForCurrentProcess()->AppendSwitch( | 237 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| 240 switches::kUseFakeDeviceForMediaStream); | 238 switches::kUseFakeDeviceForMediaStream); |
| 241 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); | 239 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); |
| 242 host_ = new MockAudioRendererHost( | 240 host_ = new MockAudioRendererHost( |
| 243 &auth_run_loop_, render_process_host_.GetID(), audio_manager_.get(), | 241 &auth_run_loop_, render_process_host_.GetID(), audio_manager_.get(), |
| 244 &mirroring_manager_, MediaInternals::GetInstance(), | 242 &mirroring_manager_, media_stream_manager_.get(), kSalt); |
| 245 media_stream_manager_.get(), kSalt); | |
| 246 | 243 |
| 247 // Simulate IPC channel connected. | 244 // Simulate IPC channel connected. |
| 248 host_->set_peer_process_for_testing(base::Process::Current()); | 245 host_->set_peer_process_for_testing(base::Process::Current()); |
| 249 } | 246 } |
| 250 | 247 |
| 251 ~AudioRendererHostTest() override { | 248 ~AudioRendererHostTest() override { |
| 252 // Simulate closing the IPC channel and give the audio thread time to close | 249 // Simulate closing the IPC channel and give the audio thread time to close |
| 253 // the underlying streams. | 250 // the underlying streams. |
| 254 host_->OnChannelClosing(); | 251 host_->OnChannelClosing(); |
| 255 SyncWithAudioThread(); | 252 SyncWithAudioThread(); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 ? media::OUTPUT_DEVICE_STATUS_OK | 331 ? media::OUTPUT_DEVICE_STATUS_OK |
| 335 : device_id == kBadDeviceId | 332 : device_id == kBadDeviceId |
| 336 ? media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED | 333 ? media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED |
| 337 : media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND; | 334 : media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND; |
| 338 | 335 |
| 339 if (expect_onauthorized) | 336 if (expect_onauthorized) |
| 340 EXPECT_CALL(*host_.get(), | 337 EXPECT_CALL(*host_.get(), |
| 341 OnDeviceAuthorized(kStreamId, expected_device_status, _, _)); | 338 OnDeviceAuthorized(kStreamId, expected_device_status, _, _)); |
| 342 | 339 |
| 343 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) { | 340 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) { |
| 344 EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _)); | 341 EXPECT_CALL(*host_.get(), WasNotifiedOfCreation(kStreamId, _)); |
| 345 EXPECT_CALL(mirroring_manager_, AddDiverter(render_process_host_.GetID(), | 342 EXPECT_CALL(mirroring_manager_, AddDiverter(render_process_host_.GetID(), |
| 346 kRenderFrameId, NotNull())) | 343 kRenderFrameId, NotNull())) |
| 347 .RetiresOnSaturation(); | 344 .RetiresOnSaturation(); |
| 348 } | 345 } |
| 349 | 346 |
| 350 // Send a create stream message to the audio output stream and wait until | 347 // Send a create stream message to the audio output stream and wait until |
| 351 // we receive the created message. | 348 // we receive the created message. |
| 352 media::AudioParameters params( | 349 media::AudioParameters params( |
| 353 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO, | 350 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO, |
| 354 media::AudioParameters::kAudioCDSampleRate, 16, | 351 media::AudioParameters::kAudioCDSampleRate, 16, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 380 SyncWithAudioThread(); | 377 SyncWithAudioThread(); |
| 381 } | 378 } |
| 382 | 379 |
| 383 void CreateWithoutWaitingForAuth(const std::string& device_id) { | 380 void CreateWithoutWaitingForAuth(const std::string& device_id) { |
| 384 Create(device_id, url::Origin(GURL(kSecurityOrigin)), false, false); | 381 Create(device_id, url::Origin(GURL(kSecurityOrigin)), false, false); |
| 385 } | 382 } |
| 386 | 383 |
| 387 void CreateWithInvalidRenderFrameId() { | 384 void CreateWithInvalidRenderFrameId() { |
| 388 // When creating a stream with an invalid render frame ID, the host will | 385 // When creating a stream with an invalid render frame ID, the host will |
| 389 // reply with a stream error message. | 386 // reply with a stream error message. |
| 390 EXPECT_CALL(*host_, OnStreamError(kStreamId)); | 387 EXPECT_CALL(*host_, WasNotifiedOfError(kStreamId)); |
| 391 | 388 |
| 392 // However, validation does not block stream creation, so these method calls | 389 // However, validation does not block stream creation, so these method calls |
| 393 // might be made: | 390 // might be made: |
| 394 EXPECT_CALL(*host_, OnStreamCreated(kStreamId, _)).Times(AtLeast(0)); | 391 EXPECT_CALL(*host_, WasNotifiedOfCreation(kStreamId, _)).Times(AtLeast(0)); |
| 395 EXPECT_CALL(mirroring_manager_, AddDiverter(_, _, _)).Times(AtLeast(0)); | 392 EXPECT_CALL(mirroring_manager_, AddDiverter(_, _, _)).Times(AtLeast(0)); |
| 396 EXPECT_CALL(mirroring_manager_, RemoveDiverter(_)).Times(AtLeast(0)); | 393 EXPECT_CALL(mirroring_manager_, RemoveDiverter(_)).Times(AtLeast(0)); |
| 397 | 394 |
| 398 // Provide a seemingly-valid render frame ID; and it should be rejected when | 395 // Provide a seemingly-valid render frame ID; and it should be rejected when |
| 399 // AudioRendererHost calls ValidateRenderFrameId(). | 396 // AudioRendererHost calls ValidateRenderFrameId(). |
| 400 const int kInvalidRenderFrameId = kRenderFrameId + 1; | 397 const int kInvalidRenderFrameId = kRenderFrameId + 1; |
| 401 const media::AudioParameters params( | 398 const media::AudioParameters params( |
| 402 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO, | 399 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO, |
| 403 media::AudioParameters::kAudioCDSampleRate, 16, | 400 media::AudioParameters::kAudioCDSampleRate, 16, |
| 404 media::AudioParameters::kAudioCDSampleRate / 10); | 401 media::AudioParameters::kAudioCDSampleRate / 10); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 423 // we receive the created message. | 420 // we receive the created message. |
| 424 media::AudioParameters params( | 421 media::AudioParameters params( |
| 425 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO, | 422 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO, |
| 426 media::AudioParameters::kAudioCDSampleRate, 16, | 423 media::AudioParameters::kAudioCDSampleRate, 16, |
| 427 media::AudioParameters::kAudioCDSampleRate / 10); | 424 media::AudioParameters::kAudioCDSampleRate / 10); |
| 428 | 425 |
| 429 EXPECT_CALL(*host_.get(), | 426 EXPECT_CALL(*host_.get(), |
| 430 OnDeviceAuthorized(kStreamId, media::OUTPUT_DEVICE_STATUS_OK, _, | 427 OnDeviceAuthorized(kStreamId, media::OUTPUT_DEVICE_STATUS_OK, _, |
| 431 hashed_output_id)) | 428 hashed_output_id)) |
| 432 .Times(1); | 429 .Times(1); |
| 433 EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _)); | 430 EXPECT_CALL(*host_.get(), WasNotifiedOfCreation(kStreamId, _)); |
| 434 EXPECT_CALL(mirroring_manager_, AddDiverter(render_process_host_.GetID(), | 431 EXPECT_CALL(mirroring_manager_, AddDiverter(render_process_host_.GetID(), |
| 435 kRenderFrameId, NotNull())) | 432 kRenderFrameId, NotNull())) |
| 436 .RetiresOnSaturation(); | 433 .RetiresOnSaturation(); |
| 437 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull())) | 434 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull())) |
| 438 .RetiresOnSaturation(); | 435 .RetiresOnSaturation(); |
| 439 | 436 |
| 440 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id, | 437 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id, |
| 441 /*device id*/ std::string(), | 438 /*device id*/ std::string(), |
| 442 security_origin); | 439 security_origin); |
| 443 | 440 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 464 host_->OnPauseStream(kStreamId); | 461 host_->OnPauseStream(kStreamId); |
| 465 SyncWithAudioThread(); | 462 SyncWithAudioThread(); |
| 466 } | 463 } |
| 467 | 464 |
| 468 void SetVolume(double volume) { | 465 void SetVolume(double volume) { |
| 469 host_->OnSetVolume(kStreamId, volume); | 466 host_->OnSetVolume(kStreamId, volume); |
| 470 SyncWithAudioThread(); | 467 SyncWithAudioThread(); |
| 471 } | 468 } |
| 472 | 469 |
| 473 void SimulateError() { | 470 void SimulateError() { |
| 474 EXPECT_EQ(1u, host_->audio_entries_.size()) | 471 EXPECT_EQ(1u, host_->delegates_.size()) |
| 475 << "Calls Create() before calling this method"; | 472 << "Calls Create() before calling this method"; |
| 476 | 473 |
| 477 // Expect an error signal sent through IPC. | 474 // Expect an error signal sent through IPC. |
| 478 EXPECT_CALL(*host_.get(), OnStreamError(kStreamId)); | 475 EXPECT_CALL(*host_.get(), WasNotifiedOfError(kStreamId)); |
| 479 | 476 |
| 480 // Simulate an error sent from the audio device. | 477 // Simulate an error sent from the audio device. |
| 481 host_->ReportErrorAndClose(kStreamId); | 478 host_->OnStreamError(kStreamId); |
| 482 SyncWithAudioThread(); | 479 SyncWithAudioThread(); |
| 483 | 480 |
| 484 // Expect the audio stream record is removed. | 481 // Expect the audio stream record is removed. |
| 485 EXPECT_EQ(0u, host_->audio_entries_.size()); | 482 EXPECT_EQ(0u, host_->delegates_.size()); |
| 486 } | 483 } |
| 487 | 484 |
| 488 // SyncWithAudioThread() waits until all pending tasks on the audio thread | 485 // SyncWithAudioThread() waits until all pending tasks on the audio thread |
| 489 // are executed while also processing pending task in message_loop_ on the | 486 // are executed while also processing pending task in message_loop_ on the |
| 490 // current thread. It is used to synchronize with the audio thread when we are | 487 // current thread. It is used to synchronize with the audio thread when we are |
| 491 // closing an audio stream. | 488 // closing an audio stream. |
| 492 void SyncWithAudioThread() { | 489 void SyncWithAudioThread() { |
| 493 base::RunLoop().RunUntilIdle(); | 490 base::RunLoop().RunUntilIdle(); |
| 494 | 491 |
| 495 base::RunLoop run_loop; | 492 base::RunLoop run_loop; |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 618 } | 615 } |
| 619 | 616 |
| 620 TEST_F(AudioRendererHostTest, CreateFailsForInvalidRenderFrame) { | 617 TEST_F(AudioRendererHostTest, CreateFailsForInvalidRenderFrame) { |
| 621 CreateWithInvalidRenderFrameId(); | 618 CreateWithInvalidRenderFrameId(); |
| 622 Close(); | 619 Close(); |
| 623 } | 620 } |
| 624 | 621 |
| 625 // TODO(hclam): Add tests for data conversation in low latency mode. | 622 // TODO(hclam): Add tests for data conversation in low latency mode. |
| 626 | 623 |
| 627 } // namespace content | 624 } // namespace content |
| OLD | NEW |