Chromium Code Reviews| 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 22 matching lines...) Expand all Loading... | |
| 33 using ::testing::DoAll; | 33 using ::testing::DoAll; |
| 34 using ::testing::NotNull; | 34 using ::testing::NotNull; |
| 35 | 35 |
| 36 namespace content { | 36 namespace content { |
| 37 | 37 |
| 38 namespace { | 38 namespace { |
| 39 const int kRenderProcessId = 1; | 39 const int kRenderProcessId = 1; |
| 40 const int kRenderFrameId = 5; | 40 const int kRenderFrameId = 5; |
| 41 const int kStreamId = 50; | 41 const int kStreamId = 50; |
| 42 const char kSecurityOrigin[] = "http://localhost"; | 42 const char kSecurityOrigin[] = "http://localhost"; |
| 43 const char kBadSecurityOrigin[] = "about:about"; | |
| 43 const char kDefaultDeviceId[] = ""; | 44 const char kDefaultDeviceId[] = ""; |
| 45 const char kNondefaultDeviceId[] = | |
| 46 "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; | |
| 44 const char kBadDeviceId[] = | 47 const char kBadDeviceId[] = |
| 45 "badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad1"; | 48 "badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad1"; |
| 46 const char kInvalidDeviceId[] = "invalid-device-id"; | 49 const char kInvalidDeviceId[] = "invalid-device-id"; |
| 47 | 50 |
| 48 void ValidateRenderFrameId(int render_process_id, | 51 void ValidateRenderFrameId(int render_process_id, |
| 49 int render_frame_id, | 52 int render_frame_id, |
| 50 const base::Callback<void(bool)>& callback) { | 53 const base::Callback<void(bool)>& callback) { |
| 51 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 54 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 52 const bool frame_exists = (render_process_id == kRenderProcessId && | 55 const bool frame_exists = (render_process_id == kRenderProcessId && |
| 53 render_frame_id == kRenderFrameId); | 56 render_frame_id == kRenderFrameId); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 85 mirroring_manager, | 88 mirroring_manager, |
| 86 media_internals, | 89 media_internals, |
| 87 media_stream_manager, | 90 media_stream_manager, |
| 88 salt), | 91 salt), |
| 89 shared_memory_length_(0), | 92 shared_memory_length_(0), |
| 90 auth_run_loop_(auth_run_loop) { | 93 auth_run_loop_(auth_run_loop) { |
| 91 set_render_frame_id_validate_function_for_testing(&ValidateRenderFrameId); | 94 set_render_frame_id_validate_function_for_testing(&ValidateRenderFrameId); |
| 92 } | 95 } |
| 93 | 96 |
| 94 // A list of mock methods. | 97 // A list of mock methods. |
| 98 MOCK_METHOD0(ShutdownForBadMessage, void()); | |
| 95 MOCK_METHOD4(OnDeviceAuthorized, | 99 MOCK_METHOD4(OnDeviceAuthorized, |
| 96 void(int stream_id, | 100 void(int stream_id, |
| 97 media::OutputDeviceStatus device_status, | 101 media::OutputDeviceStatus device_status, |
| 98 const media::AudioParameters& output_params, | 102 const media::AudioParameters& output_params, |
| 99 const std::string& matched_device_id)); | 103 const std::string& matched_device_id)); |
| 100 MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length)); | 104 MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length)); |
| 101 MOCK_METHOD1(OnStreamPlaying, void(int stream_id)); | 105 MOCK_METHOD1(OnStreamPlaying, void(int stream_id)); |
| 102 MOCK_METHOD1(OnStreamPaused, void(int stream_id)); | 106 MOCK_METHOD1(OnStreamPaused, void(int stream_id)); |
| 103 MOCK_METHOD1(OnStreamError, void(int stream_id)); | 107 MOCK_METHOD1(OnStreamError, void(int stream_id)); |
| 104 | 108 |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 196 audio_manager_ = media::AudioManager::CreateForTesting( | 200 audio_manager_ = media::AudioManager::CreateForTesting( |
| 197 base::ThreadTaskRunnerHandle::Get()); | 201 base::ThreadTaskRunnerHandle::Get()); |
| 198 base::CommandLine::ForCurrentProcess()->AppendSwitch( | 202 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| 199 switches::kUseFakeDeviceForMediaStream); | 203 switches::kUseFakeDeviceForMediaStream); |
| 200 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); | 204 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); |
| 201 host_ = new MockAudioRendererHost( | 205 host_ = new MockAudioRendererHost( |
| 202 &auth_run_loop_, audio_manager_.get(), &mirroring_manager_, | 206 &auth_run_loop_, audio_manager_.get(), &mirroring_manager_, |
| 203 MediaInternals::GetInstance(), media_stream_manager_.get(), | 207 MediaInternals::GetInstance(), media_stream_manager_.get(), |
| 204 std::string()); | 208 std::string()); |
| 205 | 209 |
| 210 EXPECT_CALL(*host_, ShutdownForBadMessage()).Times(0); | |
| 211 | |
| 206 // Simulate IPC channel connected. | 212 // Simulate IPC channel connected. |
| 207 host_->set_peer_process_for_testing(base::Process::Current()); | 213 host_->set_peer_process_for_testing(base::Process::Current()); |
| 208 } | 214 } |
| 209 | 215 |
| 210 ~AudioRendererHostTest() override { | 216 ~AudioRendererHostTest() override { |
| 211 // Simulate closing the IPC channel and give the audio thread time to close | 217 // Simulate closing the IPC channel and give the audio thread time to close |
| 212 // the underlying streams. | 218 // the underlying streams. |
| 213 host_->OnChannelClosing(); | 219 host_->OnChannelClosing(); |
| 214 SyncWithAudioThread(); | 220 SyncWithAudioThread(); |
| 215 | 221 |
| 216 // Release the reference to the mock object. The object will be destructed | 222 // Release the reference to the mock object. The object will be destructed |
| 217 // on message_loop_. | 223 // on message_loop_. |
| 218 host_ = NULL; | 224 host_ = NULL; |
| 219 } | 225 } |
| 220 | 226 |
| 221 protected: | 227 protected: |
| 222 void Create() { | 228 void Create() { |
| 223 Create(false, kDefaultDeviceId, url::Origin(GURL(kSecurityOrigin))); | 229 Create(false, kDefaultDeviceId, url::Origin(GURL(kSecurityOrigin)), true); |
| 224 } | 230 } |
| 225 | 231 |
| 226 void Create(bool unified_stream, | 232 void Create(bool unified_stream, |
| 227 const std::string& device_id, | 233 const std::string& device_id, |
| 228 const url::Origin& security_origin) { | 234 const url::Origin& security_origin, |
| 235 bool wait_for_auth) { | |
| 229 media::OutputDeviceStatus expected_device_status = | 236 media::OutputDeviceStatus expected_device_status = |
| 230 device_id == kDefaultDeviceId | 237 device_id == kDefaultDeviceId |
| 231 ? media::OUTPUT_DEVICE_STATUS_OK | 238 ? media::OUTPUT_DEVICE_STATUS_OK |
| 232 : device_id == kBadDeviceId | 239 : device_id == kBadDeviceId |
| 233 ? media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED | 240 ? media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED |
| 234 : media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND; | 241 : media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND; |
| 235 | 242 |
| 236 EXPECT_CALL(*host_.get(), | 243 EXPECT_CALL(*host_.get(), |
| 237 OnDeviceAuthorized(kStreamId, expected_device_status, _, _)); | 244 OnDeviceAuthorized(kStreamId, expected_device_status, _, _)); |
| 238 | 245 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 250 media::AudioParameters::kAudioCDSampleRate, 16, | 257 media::AudioParameters::kAudioCDSampleRate, 16, |
| 251 media::AudioParameters::kAudioCDSampleRate / 10); | 258 media::AudioParameters::kAudioCDSampleRate / 10); |
| 252 int session_id = 0; | 259 int session_id = 0; |
| 253 if (unified_stream) { | 260 if (unified_stream) { |
| 254 // Use AudioInputDeviceManager::kFakeOpenSessionId as the session id to | 261 // Use AudioInputDeviceManager::kFakeOpenSessionId as the session id to |
| 255 // pass the permission check. | 262 // pass the permission check. |
| 256 session_id = AudioInputDeviceManager::kFakeOpenSessionId; | 263 session_id = AudioInputDeviceManager::kFakeOpenSessionId; |
| 257 } | 264 } |
| 258 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id, | 265 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id, |
| 259 device_id, security_origin); | 266 device_id, security_origin); |
| 260 auth_run_loop_.Run(); | 267 if (wait_for_auth) |
| 261 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) { | 268 auth_run_loop_.Run(); |
| 269 | |
| 270 if (!wait_for_auth || | |
| 271 expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) | |
| 262 host_->OnCreateStream(kStreamId, kRenderFrameId, params); | 272 host_->OnCreateStream(kStreamId, kRenderFrameId, params); |
| 263 | 273 |
| 274 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) | |
| 264 // At some point in the future, a corresponding RemoveDiverter() call must | 275 // At some point in the future, a corresponding RemoveDiverter() call must |
| 265 // be made. | 276 // be made. |
| 266 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull())) | 277 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull())) |
| 267 .RetiresOnSaturation(); | 278 .RetiresOnSaturation(); |
| 268 } | |
| 269 SyncWithAudioThread(); | 279 SyncWithAudioThread(); |
| 270 } | 280 } |
| 271 | 281 |
| 282 void RequestDeviceAuthorizationWithBadOrigin( | |
| 283 const std::string& device_id, | |
| 284 const url::Origin& security_origin) { | |
| 285 media::AudioParameters params( | |
|
chcunningham
2016/10/04 15:39:30
I don't think you're using params here.
Max Morin
2016/10/05 08:58:36
Done.
| |
| 286 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO, | |
| 287 media::AudioParameters::kAudioCDSampleRate, 16, | |
| 288 media::AudioParameters::kAudioCDSampleRate / 10); | |
| 289 int session_id = 0; | |
| 290 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id, | |
| 291 device_id, security_origin); | |
| 292 SyncWithAudioThread(); | |
| 293 } | |
| 294 | |
| 295 void CreateWithoutWaitingForAuth(const std::string& device_id) { | |
| 296 Create(false, device_id, url::Origin(GURL(kSecurityOrigin)), false); | |
| 297 } | |
| 298 | |
| 272 void CreateWithInvalidRenderFrameId() { | 299 void CreateWithInvalidRenderFrameId() { |
| 273 // When creating a stream with an invalid render frame ID, the host will | 300 // When creating a stream with an invalid render frame ID, the host will |
| 274 // reply with a stream error message. | 301 // reply with a stream error message. |
| 275 EXPECT_CALL(*host_, OnStreamError(kStreamId)); | 302 EXPECT_CALL(*host_, OnStreamError(kStreamId)); |
| 276 | 303 |
| 277 // However, validation does not block stream creation, so these method calls | 304 // However, validation does not block stream creation, so these method calls |
| 278 // might be made: | 305 // might be made: |
| 279 EXPECT_CALL(*host_, OnStreamCreated(kStreamId, _)).Times(AtLeast(0)); | 306 EXPECT_CALL(*host_, OnStreamCreated(kStreamId, _)).Times(AtLeast(0)); |
| 280 EXPECT_CALL(mirroring_manager_, AddDiverter(_, _, _)).Times(AtLeast(0)); | 307 EXPECT_CALL(mirroring_manager_, AddDiverter(_, _, _)).Times(AtLeast(0)); |
| 281 EXPECT_CALL(mirroring_manager_, RemoveDiverter(_)).Times(AtLeast(0)); | 308 EXPECT_CALL(mirroring_manager_, RemoveDiverter(_)).Times(AtLeast(0)); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 336 // closing an audio stream. | 363 // closing an audio stream. |
| 337 void SyncWithAudioThread() { | 364 void SyncWithAudioThread() { |
| 338 base::RunLoop().RunUntilIdle(); | 365 base::RunLoop().RunUntilIdle(); |
| 339 | 366 |
| 340 base::RunLoop run_loop; | 367 base::RunLoop run_loop; |
| 341 audio_manager_->GetTaskRunner()->PostTask( | 368 audio_manager_->GetTaskRunner()->PostTask( |
| 342 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure())); | 369 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure())); |
| 343 run_loop.Run(); | 370 run_loop.Run(); |
| 344 } | 371 } |
| 345 | 372 |
| 373 void ExpectShutdown() { | |
| 374 EXPECT_CALL(*host_, ShutdownForBadMessage()).Times(1); | |
| 375 } | |
| 376 | |
| 346 private: | 377 private: |
| 347 // MediaStreamManager uses a DestructionObserver, so it must outlive the | 378 // MediaStreamManager uses a DestructionObserver, so it must outlive the |
| 348 // TestBrowserThreadBundle. | 379 // TestBrowserThreadBundle. |
| 349 std::unique_ptr<MediaStreamManager> media_stream_manager_; | 380 std::unique_ptr<MediaStreamManager> media_stream_manager_; |
| 350 TestBrowserThreadBundle thread_bundle_; | 381 TestBrowserThreadBundle thread_bundle_; |
| 351 media::ScopedAudioManagerPtr audio_manager_; | 382 media::ScopedAudioManagerPtr audio_manager_; |
| 352 MockAudioMirroringManager mirroring_manager_; | 383 MockAudioMirroringManager mirroring_manager_; |
| 353 scoped_refptr<MockAudioRendererHost> host_; | 384 scoped_refptr<MockAudioRendererHost> host_; |
| 354 base::RunLoop auth_run_loop_; | 385 base::RunLoop auth_run_loop_; |
| 355 | 386 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 410 // the audio device is closed but the render process try to close the | 441 // the audio device is closed but the render process try to close the |
| 411 // audio stream again. | 442 // audio stream again. |
| 412 TEST_F(AudioRendererHostTest, SimulateErrorAndClose) { | 443 TEST_F(AudioRendererHostTest, SimulateErrorAndClose) { |
| 413 Create(); | 444 Create(); |
| 414 Play(); | 445 Play(); |
| 415 SimulateError(); | 446 SimulateError(); |
| 416 Close(); | 447 Close(); |
| 417 } | 448 } |
| 418 | 449 |
| 419 TEST_F(AudioRendererHostTest, CreateUnifiedStreamAndClose) { | 450 TEST_F(AudioRendererHostTest, CreateUnifiedStreamAndClose) { |
| 420 Create(true, kDefaultDeviceId, url::Origin(GURL(kSecurityOrigin))); | 451 Create(true, kDefaultDeviceId, url::Origin(GURL(kSecurityOrigin)), true); |
| 421 Close(); | 452 Close(); |
| 422 } | 453 } |
| 423 | 454 |
| 424 TEST_F(AudioRendererHostTest, CreateUnauthorizedDevice) { | 455 TEST_F(AudioRendererHostTest, CreateUnauthorizedDevice) { |
| 425 Create(false, kBadDeviceId, url::Origin(GURL(kSecurityOrigin))); | 456 Create(false, kBadDeviceId, url::Origin(GURL(kSecurityOrigin)), true); |
| 457 Close(); | |
| 458 } | |
| 459 | |
| 460 TEST_F(AudioRendererHostTest, CreateDeviceWithAuthorizationPendingIsError) { | |
| 461 ExpectShutdown(); | |
| 462 CreateWithoutWaitingForAuth(kBadDeviceId); | |
| 463 Close(); | |
| 464 } | |
| 465 | |
| 466 TEST_F(AudioRendererHostTest, CreateDeviceWithBadSecurityOrigin) { | |
| 467 ExpectShutdown(); | |
| 468 RequestDeviceAuthorizationWithBadOrigin( | |
| 469 kNondefaultDeviceId, url::Origin(GURL(kBadSecurityOrigin))); | |
|
chcunningham
2016/10/04 15:39:30
Do you mean to pass in the bad origin? The method
Max Morin
2016/10/05 08:58:35
Done.
| |
| 426 Close(); | 470 Close(); |
| 427 } | 471 } |
| 428 | 472 |
| 429 TEST_F(AudioRendererHostTest, CreateInvalidDevice) { | 473 TEST_F(AudioRendererHostTest, CreateInvalidDevice) { |
| 430 Create(false, kInvalidDeviceId, url::Origin(GURL(kSecurityOrigin))); | 474 Create(false, kInvalidDeviceId, url::Origin(GURL(kSecurityOrigin)), true); |
| 431 Close(); | 475 Close(); |
| 432 } | 476 } |
| 433 | 477 |
| 434 TEST_F(AudioRendererHostTest, CreateFailsForInvalidRenderFrame) { | 478 TEST_F(AudioRendererHostTest, CreateFailsForInvalidRenderFrame) { |
| 435 CreateWithInvalidRenderFrameId(); | 479 CreateWithInvalidRenderFrameId(); |
| 436 Close(); | 480 Close(); |
| 437 } | 481 } |
| 438 | 482 |
| 439 // TODO(hclam): Add tests for data conversation in low latency mode. | 483 // TODO(hclam): Add tests for data conversation in low latency mode. |
| 440 | 484 |
| 441 } // namespace content | 485 } // namespace content |
| OLD | NEW |