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 "base/bind.h" | 5 #include "base/bind.h" |
| 6 #include "base/environment.h" | |
| 7 #include "base/memory/scoped_ptr.h" | 6 #include "base/memory/scoped_ptr.h" |
| 8 #include "base/message_loop/message_loop.h" | 7 #include "base/run_loop.h" |
| 9 #include "base/sync_socket.h" | 8 #include "base/sync_socket.h" |
| 10 #include "content/browser/browser_thread_impl.h" | 9 #include "content/browser/media/media_internals.h" |
| 11 #include "content/browser/renderer_host/media/audio_input_device_manager.h" | 10 #include "content/browser/renderer_host/media/audio_input_device_manager.h" |
| 12 #include "content/browser/renderer_host/media/audio_mirroring_manager.h" | 11 #include "content/browser/renderer_host/media/audio_mirroring_manager.h" |
| 13 #include "content/browser/renderer_host/media/audio_renderer_host.h" | 12 #include "content/browser/renderer_host/media/audio_renderer_host.h" |
| 14 #include "content/browser/renderer_host/media/media_stream_manager.h" | 13 #include "content/browser/renderer_host/media/media_stream_manager.h" |
| 15 #include "content/browser/renderer_host/media/mock_media_observer.h" | |
| 16 #include "content/common/media/audio_messages.h" | 14 #include "content/common/media/audio_messages.h" |
| 17 #include "content/common/media/media_stream_options.h" | 15 #include "content/public/test/test_browser_thread_bundle.h" |
| 18 #include "ipc/ipc_message_utils.h" | 16 #include "ipc/ipc_message_utils.h" |
| 19 #include "media/audio/audio_manager.h" | 17 #include "media/audio/audio_manager.h" |
| 20 #include "media/audio/audio_manager_base.h" | 18 #include "media/base/bind_to_loop.h" |
| 21 #include "media/audio/fake_audio_output_stream.h" | |
| 22 #include "net/url_request/url_request_context.h" | |
| 23 #include "testing/gmock/include/gmock/gmock.h" | 19 #include "testing/gmock/include/gmock/gmock.h" |
| 24 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
| 25 | 21 |
| 26 using ::testing::_; | 22 using ::testing::_; |
| 27 using ::testing::Assign; | 23 using ::testing::Assign; |
| 28 using ::testing::DoAll; | 24 using ::testing::DoAll; |
| 29 using ::testing::NotNull; | 25 using ::testing::NotNull; |
| 30 | 26 |
| 27 namespace { | |
| 28 const int kRenderProcessId = 1; | |
| 29 const int kRenderViewId = 4; | |
| 30 const int kStreamId = 50; | |
| 31 } // namespace | |
| 32 | |
| 31 namespace content { | 33 namespace content { |
| 32 | 34 |
| 33 static const int kRenderProcessId = 1; | |
| 34 static const int kRenderViewId = 4; | |
| 35 static const int kStreamId = 50; | |
| 36 | |
| 37 class MockAudioMirroringManager : public AudioMirroringManager { | 35 class MockAudioMirroringManager : public AudioMirroringManager { |
| 38 public: | 36 public: |
| 39 MockAudioMirroringManager() {} | 37 MockAudioMirroringManager() {} |
| 40 virtual ~MockAudioMirroringManager() {} | 38 virtual ~MockAudioMirroringManager() {} |
| 41 | 39 |
| 42 MOCK_METHOD3(AddDiverter, | 40 MOCK_METHOD3(AddDiverter, |
| 43 void(int render_process_id, int render_view_id, | 41 void(int render_process_id, |
| 42 int render_view_id, | |
| 44 Diverter* diverter)); | 43 Diverter* diverter)); |
| 45 MOCK_METHOD3(RemoveDiverter, | 44 MOCK_METHOD3(RemoveDiverter, |
| 46 void(int render_process_id, int render_view_id, | 45 void(int render_process_id, |
| 46 int render_view_id, | |
| 47 Diverter* diverter)); | 47 Diverter* diverter)); |
| 48 | 48 |
| 49 private: | 49 private: |
| 50 DISALLOW_COPY_AND_ASSIGN(MockAudioMirroringManager); | 50 DISALLOW_COPY_AND_ASSIGN(MockAudioMirroringManager); |
| 51 }; | 51 }; |
| 52 | 52 |
| 53 class MockAudioRendererHost : public AudioRendererHost { | 53 class MockAudioRendererHost : public AudioRendererHost { |
| 54 public: | 54 public: |
| 55 explicit MockAudioRendererHost( | 55 explicit MockAudioRendererHost(media::AudioManager* audio_manager, |
|
tommi (sloooow) - chröme
2013/11/22 11:55:31
no need for explicit
DaleCurtis
2013/11/22 20:33:33
Done.
| |
| 56 media::AudioManager* audio_manager, | 56 AudioMirroringManager* mirroring_manager, |
| 57 AudioMirroringManager* mirroring_manager, | 57 MediaInternals* media_internals, |
| 58 MediaInternals* media_internals, | 58 MediaStreamManager* media_stream_manager) |
| 59 MediaStreamManager* media_stream_manager) | |
| 60 : AudioRendererHost(kRenderProcessId, | 59 : AudioRendererHost(kRenderProcessId, |
| 61 audio_manager, | 60 audio_manager, |
| 62 mirroring_manager, | 61 mirroring_manager, |
| 63 media_internals, | 62 media_internals, |
| 64 media_stream_manager), | 63 media_stream_manager), |
| 65 shared_memory_length_(0) { | 64 shared_memory_length_(0) {} |
| 66 } | |
| 67 | 65 |
| 68 // A list of mock methods. | 66 // A list of mock methods. |
| 69 MOCK_METHOD2(OnStreamCreated, | 67 MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length)); |
| 70 void(int stream_id, int length)); | |
| 71 MOCK_METHOD1(OnStreamPlaying, void(int stream_id)); | 68 MOCK_METHOD1(OnStreamPlaying, void(int stream_id)); |
| 72 MOCK_METHOD1(OnStreamPaused, void(int stream_id)); | 69 MOCK_METHOD1(OnStreamPaused, void(int stream_id)); |
| 73 MOCK_METHOD1(OnStreamError, void(int stream_id)); | 70 MOCK_METHOD1(OnStreamError, void(int stream_id)); |
| 74 | 71 |
| 75 private: | 72 private: |
| 76 virtual ~MockAudioRendererHost() { | 73 virtual ~MockAudioRendererHost() { |
| 77 // Make sure all audio streams have been deleted. | 74 // Make sure all audio streams have been deleted. |
| 78 EXPECT_TRUE(audio_entries_.empty()); | 75 EXPECT_TRUE(audio_entries_.empty()); |
| 79 } | 76 } |
| 80 | 77 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 93 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamStateChanged, | 90 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamStateChanged, |
| 94 OnStreamStateChanged) | 91 OnStreamStateChanged) |
| 95 IPC_MESSAGE_UNHANDLED(handled = false) | 92 IPC_MESSAGE_UNHANDLED(handled = false) |
| 96 IPC_END_MESSAGE_MAP() | 93 IPC_END_MESSAGE_MAP() |
| 97 EXPECT_TRUE(handled); | 94 EXPECT_TRUE(handled); |
| 98 | 95 |
| 99 delete message; | 96 delete message; |
| 100 return true; | 97 return true; |
| 101 } | 98 } |
| 102 | 99 |
| 103 void OnStreamCreated(const IPC::Message& msg, int stream_id, | 100 void OnStreamCreated(const IPC::Message& msg, |
| 101 int stream_id, | |
| 104 base::SharedMemoryHandle handle, | 102 base::SharedMemoryHandle handle, |
| 105 #if defined(OS_WIN) | 103 #if defined(OS_WIN) |
| 106 base::SyncSocket::Handle socket_handle, | 104 base::SyncSocket::Handle socket_handle, |
| 107 #else | 105 #else |
| 108 base::FileDescriptor socket_descriptor, | 106 base::FileDescriptor socket_descriptor, |
| 109 #endif | 107 #endif |
| 110 uint32 length) { | 108 uint32 length) { |
| 111 // Maps the shared memory. | 109 // Maps the shared memory. |
| 112 shared_memory_.reset(new base::SharedMemory(handle, false)); | 110 shared_memory_.reset(new base::SharedMemory(handle, false)); |
| 113 CHECK(shared_memory_->Map(length)); | 111 CHECK(shared_memory_->Map(length)); |
| 114 CHECK(shared_memory_->memory()); | 112 CHECK(shared_memory_->memory()); |
| 115 shared_memory_length_ = length; | 113 shared_memory_length_ = length; |
| 116 | 114 |
| 117 // Create the SyncSocket using the handle. | 115 // Create the SyncSocket using the handle. |
| 118 base::SyncSocket::Handle sync_socket_handle; | 116 base::SyncSocket::Handle sync_socket_handle; |
| 119 #if defined(OS_WIN) | 117 #if defined(OS_WIN) |
| 120 sync_socket_handle = socket_handle; | 118 sync_socket_handle = socket_handle; |
| 121 #else | 119 #else |
| 122 sync_socket_handle = socket_descriptor.fd; | 120 sync_socket_handle = socket_descriptor.fd; |
| 123 #endif | 121 #endif |
| 124 sync_socket_.reset(new base::SyncSocket(sync_socket_handle)); | 122 sync_socket_.reset(new base::SyncSocket(sync_socket_handle)); |
| 125 | 123 |
| 126 // And then delegate the call to the mock method. | 124 // And then delegate the call to the mock method. |
| 127 OnStreamCreated(stream_id, length); | 125 OnStreamCreated(stream_id, length); |
| 128 } | 126 } |
| 129 | 127 |
| 130 void OnStreamStateChanged(const IPC::Message& msg, int stream_id, | 128 void OnStreamStateChanged(const IPC::Message& msg, |
| 129 int stream_id, | |
| 131 media::AudioOutputIPCDelegate::State state) { | 130 media::AudioOutputIPCDelegate::State state) { |
| 132 switch (state) { | 131 switch (state) { |
| 133 case media::AudioOutputIPCDelegate::kPlaying: | 132 case media::AudioOutputIPCDelegate::kPlaying: |
| 134 OnStreamPlaying(stream_id); | 133 OnStreamPlaying(stream_id); |
| 135 break; | 134 break; |
| 136 case media::AudioOutputIPCDelegate::kPaused: | 135 case media::AudioOutputIPCDelegate::kPaused: |
| 137 OnStreamPaused(stream_id); | 136 OnStreamPaused(stream_id); |
| 138 break; | 137 break; |
| 139 case media::AudioOutputIPCDelegate::kError: | 138 case media::AudioOutputIPCDelegate::kError: |
| 140 OnStreamError(stream_id); | 139 OnStreamError(stream_id); |
| 141 break; | 140 break; |
| 142 default: | 141 default: |
| 143 FAIL() << "Unknown stream state"; | 142 FAIL() << "Unknown stream state"; |
| 144 break; | 143 break; |
| 145 } | 144 } |
| 146 } | 145 } |
| 147 | 146 |
| 148 scoped_ptr<base::SharedMemory> shared_memory_; | 147 scoped_ptr<base::SharedMemory> shared_memory_; |
| 149 scoped_ptr<base::SyncSocket> sync_socket_; | 148 scoped_ptr<base::SyncSocket> sync_socket_; |
| 150 uint32 shared_memory_length_; | 149 uint32 shared_memory_length_; |
| 151 | 150 |
| 152 DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost); | 151 DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost); |
| 153 }; | 152 }; |
| 154 | 153 |
| 155 ACTION_P(QuitMessageLoop, message_loop) { | |
| 156 message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure()); | |
| 157 } | |
| 158 | |
| 159 class AudioRendererHostTest : public testing::Test { | 154 class AudioRendererHostTest : public testing::Test { |
| 160 public: | 155 public: |
| 161 AudioRendererHostTest() : is_stream_active_(false) {} | 156 AudioRendererHostTest() { |
| 162 | |
| 163 protected: | |
| 164 virtual void SetUp() { | |
| 165 // Create a message loop so AudioRendererHost can use it. | |
| 166 message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO)); | |
| 167 | |
| 168 // Claim to be on both the UI and IO threads to pass all the DCHECKS. | |
| 169 io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO, | |
| 170 message_loop_.get())); | |
| 171 ui_thread_.reset(new BrowserThreadImpl(BrowserThread::UI, | |
| 172 message_loop_.get())); | |
| 173 audio_manager_.reset(media::AudioManager::Create()); | 157 audio_manager_.reset(media::AudioManager::Create()); |
| 174 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); | 158 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); |
| 175 media_stream_manager_->UseFakeDevice(); | 159 media_stream_manager_->UseFakeDevice(); |
| 176 observer_.reset(new MockMediaInternals()); | 160 host_ = new MockAudioRendererHost(audio_manager_.get(), |
| 177 host_ = new MockAudioRendererHost( | 161 &mirroring_manager_, |
| 178 audio_manager_.get(), &mirroring_manager_, observer_.get(), | 162 MediaInternals::GetInstance(), |
| 179 media_stream_manager_.get()); | 163 media_stream_manager_.get()); |
| 180 | 164 |
| 181 // Simulate IPC channel connected. | 165 // Simulate IPC channel connected. |
| 182 host_->set_peer_pid_for_testing(base::GetCurrentProcId()); | 166 host_->set_peer_pid_for_testing(base::GetCurrentProcId()); |
| 183 } | 167 } |
| 184 | 168 |
| 185 virtual void TearDown() { | 169 virtual ~AudioRendererHostTest() { |
| 186 // Simulate closing the IPC channel. | 170 // Simulate closing the IPC channel. |
| 187 host_->OnChannelClosing(); | 171 host_->OnChannelClosing(); |
| 188 | 172 |
| 189 // Release the reference to the mock object. The object will be destructed | 173 // Release the reference to the mock object. The object will be destructed |
| 190 // on message_loop_. | 174 // on message_loop_. |
| 191 host_ = NULL; | 175 host_ = NULL; |
| 192 | |
| 193 // We need to continue running message_loop_ to complete all destructions. | |
| 194 SyncWithAudioThread(); | |
| 195 audio_manager_.reset(); | |
| 196 | |
| 197 // Make sure the stream has been deleted before continuing. | |
| 198 while (is_stream_active_) | |
| 199 message_loop_->Run(); | |
| 200 | |
| 201 io_thread_.reset(); | |
| 202 ui_thread_.reset(); | |
| 203 | |
| 204 // Delete the IO message loop. This will cause the MediaStreamManager to be | |
| 205 // notified so it will stop its device thread and device managers. | |
| 206 message_loop_.reset(); | |
| 207 } | 176 } |
| 208 | 177 |
| 178 protected: | |
| 209 void Create(bool unified_stream) { | 179 void Create(bool unified_stream) { |
| 210 EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _)) | 180 EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _)); |
| 211 .WillOnce(DoAll(Assign(&is_stream_active_, true), | 181 |
| 212 QuitMessageLoop(message_loop_.get()))); | |
| 213 EXPECT_CALL(mirroring_manager_, | 182 EXPECT_CALL(mirroring_manager_, |
| 214 AddDiverter(kRenderProcessId, kRenderViewId, NotNull())) | 183 AddDiverter(kRenderProcessId, kRenderViewId, NotNull())) |
| 215 .RetiresOnSaturation(); | 184 .RetiresOnSaturation(); |
| 216 | 185 |
| 217 // Send a create stream message to the audio output stream and wait until | 186 // Send a create stream message to the audio output stream and wait until |
| 218 // we receive the created message. | 187 // we receive the created message. |
| 219 int session_id; | 188 int session_id; |
| 220 media::AudioParameters params; | 189 media::AudioParameters params; |
| 221 if (unified_stream) { | 190 if (unified_stream) { |
| 222 // Use AudioInputDeviceManager::kFakeOpenSessionId as the session id to | 191 // Use AudioInputDeviceManager::kFakeOpenSessionId as the session id to |
| 223 // pass the permission check. | 192 // pass the permission check. |
| 224 session_id = AudioInputDeviceManager::kFakeOpenSessionId; | 193 session_id = AudioInputDeviceManager::kFakeOpenSessionId; |
| 225 params = media::AudioParameters( | 194 params = media::AudioParameters( |
| 226 media::AudioParameters::AUDIO_FAKE, | 195 media::AudioParameters::AUDIO_FAKE, |
| 227 media::CHANNEL_LAYOUT_STEREO, | 196 media::CHANNEL_LAYOUT_STEREO, |
| 228 2, | 197 2, |
| 229 media::AudioParameters::kAudioCDSampleRate, 16, | 198 media::AudioParameters::kAudioCDSampleRate, 16, |
| 230 media::AudioParameters::kAudioCDSampleRate / 10); | 199 media::AudioParameters::kAudioCDSampleRate / 10); |
| 231 } else { | 200 } else { |
| 232 session_id = 0; | 201 session_id = 0; |
| 233 params = media::AudioParameters( | 202 params = media::AudioParameters( |
| 234 media::AudioParameters::AUDIO_FAKE, | 203 media::AudioParameters::AUDIO_FAKE, |
| 235 media::CHANNEL_LAYOUT_STEREO, | 204 media::CHANNEL_LAYOUT_STEREO, |
| 236 media::AudioParameters::kAudioCDSampleRate, 16, | 205 media::AudioParameters::kAudioCDSampleRate, 16, |
| 237 media::AudioParameters::kAudioCDSampleRate / 10); | 206 media::AudioParameters::kAudioCDSampleRate / 10); |
| 238 } | 207 } |
| 239 host_->OnCreateStream(kStreamId, kRenderViewId, session_id, params); | 208 host_->OnCreateStream(kStreamId, kRenderViewId, session_id, params); |
| 240 message_loop_->Run(); | |
| 241 | 209 |
| 242 // At some point in the future, a corresponding RemoveDiverter() call must | 210 // At some point in the future, a corresponding RemoveDiverter() call must |
| 243 // be made. | 211 // be made. |
| 244 EXPECT_CALL(mirroring_manager_, | 212 EXPECT_CALL(mirroring_manager_, |
| 245 RemoveDiverter(kRenderProcessId, kRenderViewId, NotNull())) | 213 RemoveDiverter(kRenderProcessId, kRenderViewId, NotNull())) |
| 246 .RetiresOnSaturation(); | 214 .RetiresOnSaturation(); |
| 247 | 215 SyncWithAudioThread(); |
| 248 // All created streams should ultimately be closed. | |
| 249 EXPECT_CALL(*observer_, | |
| 250 OnSetAudioStreamStatus(_, kStreamId, "closed")); | |
| 251 | |
| 252 // Expect the audio stream will be deleted at some later point. | |
| 253 EXPECT_CALL(*observer_, OnDeleteAudioStream(_, kStreamId)) | |
| 254 .WillOnce(DoAll(Assign(&is_stream_active_, false), | |
| 255 QuitMessageLoop(message_loop_.get()))); | |
| 256 } | 216 } |
| 257 | 217 |
| 258 void Close() { | 218 void Close() { |
| 259 // Send a message to AudioRendererHost to tell it we want to close the | 219 // Send a message to AudioRendererHost to tell it we want to close the |
| 260 // stream. | 220 // stream. |
| 261 host_->OnCloseStream(kStreamId); | 221 host_->OnCloseStream(kStreamId); |
| 262 if (is_stream_active_) | 222 SyncWithAudioThread(); |
| 263 message_loop_->Run(); | |
| 264 else | |
| 265 message_loop_->RunUntilIdle(); | |
| 266 } | 223 } |
| 267 | 224 |
| 268 void Play() { | 225 void Play() { |
| 269 EXPECT_CALL(*observer_, | 226 EXPECT_CALL(*host_.get(), OnStreamPlaying(kStreamId)); |
| 270 OnSetAudioStreamPlaying(_, kStreamId, true)); | |
| 271 EXPECT_CALL(*host_.get(), OnStreamPlaying(kStreamId)) | |
| 272 .WillOnce(QuitMessageLoop(message_loop_.get())); | |
| 273 | |
| 274 host_->OnPlayStream(kStreamId); | 227 host_->OnPlayStream(kStreamId); |
| 275 message_loop_->Run(); | 228 SyncWithAudioThread(); |
| 276 } | 229 } |
| 277 | 230 |
| 278 void Pause() { | 231 void Pause() { |
| 279 EXPECT_CALL(*observer_, | 232 EXPECT_CALL(*host_.get(), OnStreamPaused(kStreamId)); |
| 280 OnSetAudioStreamPlaying(_, kStreamId, false)); | |
| 281 EXPECT_CALL(*host_.get(), OnStreamPaused(kStreamId)) | |
| 282 .WillOnce(QuitMessageLoop(message_loop_.get())); | |
| 283 | |
| 284 host_->OnPauseStream(kStreamId); | 233 host_->OnPauseStream(kStreamId); |
| 285 message_loop_->Run(); | 234 SyncWithAudioThread(); |
| 286 } | 235 } |
| 287 | 236 |
| 288 void SetVolume(double volume) { | 237 void SetVolume(double volume) { |
| 289 EXPECT_CALL(*observer_, | |
| 290 OnSetAudioStreamVolume(_, kStreamId, volume)); | |
| 291 | |
| 292 host_->OnSetVolume(kStreamId, volume); | 238 host_->OnSetVolume(kStreamId, volume); |
| 293 message_loop_->RunUntilIdle(); | 239 SyncWithAudioThread(); |
| 294 } | 240 } |
| 295 | 241 |
| 296 void SimulateError() { | 242 void SimulateError() { |
| 297 EXPECT_CALL(*observer_, | |
| 298 OnSetAudioStreamStatus(_, kStreamId, "error")); | |
| 299 EXPECT_EQ(1u, host_->audio_entries_.size()) | 243 EXPECT_EQ(1u, host_->audio_entries_.size()) |
| 300 << "Calls Create() before calling this method"; | 244 << "Calls Create() before calling this method"; |
| 301 | 245 |
| 302 // Expect an error signal sent through IPC. | 246 // Expect an error signal sent through IPC. |
| 303 EXPECT_CALL(*host_.get(), OnStreamError(kStreamId)); | 247 EXPECT_CALL(*host_.get(), OnStreamError(kStreamId)); |
| 304 | 248 |
| 305 // Simulate an error sent from the audio device. | 249 // Simulate an error sent from the audio device. |
| 306 host_->ReportErrorAndClose(kStreamId); | 250 host_->ReportErrorAndClose(kStreamId); |
| 307 SyncWithAudioThread(); | 251 SyncWithAudioThread(); |
| 308 | 252 |
| 309 // Expect the audio stream record is removed. | 253 // Expect the audio stream record is removed. |
| 310 EXPECT_EQ(0u, host_->audio_entries_.size()); | 254 EXPECT_EQ(0u, host_->audio_entries_.size()); |
| 311 } | 255 } |
| 312 | 256 |
| 313 // Called on the audio thread. | 257 // Called on the audio thread. |
| 314 static void PostQuitMessageLoop(base::MessageLoop* message_loop) { | 258 static void PostQuitMessageLoop(const base::Closure& quit_closure) { |
| 315 message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure()); | 259 quit_closure.Run(); |
| 316 } | |
| 317 | |
| 318 // Called on the main thread. | |
| 319 static void PostQuitOnAudioThread(media::AudioManager* audio_manager, | |
| 320 base::MessageLoop* message_loop) { | |
| 321 audio_manager->GetMessageLoop()->PostTask(FROM_HERE, | |
| 322 base::Bind(&PostQuitMessageLoop, message_loop)); | |
| 323 } | 260 } |
| 324 | 261 |
| 325 // SyncWithAudioThread() waits until all pending tasks on the audio thread | 262 // SyncWithAudioThread() waits until all pending tasks on the audio thread |
| 326 // are executed while also processing pending task in message_loop_ on the | 263 // are executed while also processing pending task in message_loop_ on the |
| 327 // current thread. It is used to synchronize with the audio thread when we are | 264 // current thread. It is used to synchronize with the audio thread when we are |
| 328 // closing an audio stream. | 265 // closing an audio stream. |
| 329 void SyncWithAudioThread() { | 266 void SyncWithAudioThread() { |
| 330 // Don't use scoped_refptr to addref the media::AudioManager when posting | 267 base::RunLoop().RunUntilIdle(); |
| 331 // to the thread that itself owns. | 268 |
| 332 message_loop_->PostTask( | 269 base::RunLoop run_loop; |
| 333 FROM_HERE, base::Bind(&PostQuitOnAudioThread, | 270 audio_manager_->GetMessageLoop()->PostTask( |
| 334 base::Unretained(audio_manager_.get()), | 271 FROM_HERE, media::BindToCurrentLoop(base::Bind( |
| 335 message_loop_.get())); | 272 &AudioRendererHostTest::PostQuitMessageLoop, |
|
acolwell GONE FROM CHROMIUM
2013/11/22 19:12:48
Why do you need PostQuitMessageLoop? You should be
DaleCurtis
2013/11/22 20:33:33
Derp. It was left over from a previous incarnation
| |
| 336 message_loop_->Run(); | 273 run_loop.QuitClosure()))); |
| 274 run_loop.Run(); | |
| 337 } | 275 } |
| 338 | 276 |
| 339 private: | 277 private: |
| 340 scoped_ptr<MockMediaInternals> observer_; | 278 // MediaStreamManager uses a DestructionObserver, so it must outlive the |
| 279 // TestBrowserThreadBundle. | |
| 280 scoped_ptr<MediaStreamManager> media_stream_manager_; | |
| 281 TestBrowserThreadBundle thread_bundle_; | |
| 282 scoped_ptr<media::AudioManager> audio_manager_; | |
| 341 MockAudioMirroringManager mirroring_manager_; | 283 MockAudioMirroringManager mirroring_manager_; |
| 342 scoped_refptr<MockAudioRendererHost> host_; | 284 scoped_refptr<MockAudioRendererHost> host_; |
| 343 scoped_ptr<base::MessageLoop> message_loop_; | |
| 344 scoped_ptr<BrowserThreadImpl> io_thread_; | |
| 345 scoped_ptr<BrowserThreadImpl> ui_thread_; | |
| 346 scoped_ptr<media::AudioManager> audio_manager_; | |
| 347 scoped_ptr<MediaStreamManager> media_stream_manager_; | |
| 348 | |
| 349 bool is_stream_active_; | |
| 350 | 285 |
| 351 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest); | 286 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest); |
| 352 }; | 287 }; |
| 353 | 288 |
| 354 TEST_F(AudioRendererHostTest, CreateAndClose) { | 289 TEST_F(AudioRendererHostTest, CreateAndClose) { |
| 355 Create(false); | 290 Create(false); |
| 356 Close(); | 291 Close(); |
| 357 } | 292 } |
| 358 | 293 |
| 359 // Simulate the case where a stream is not properly closed. | 294 // Simulate the case where a stream is not properly closed. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 412 } | 347 } |
| 413 | 348 |
| 414 TEST_F(AudioRendererHostTest, CreateUnifiedStreamAndClose) { | 349 TEST_F(AudioRendererHostTest, CreateUnifiedStreamAndClose) { |
| 415 Create(true); | 350 Create(true); |
| 416 Close(); | 351 Close(); |
| 417 } | 352 } |
| 418 | 353 |
| 419 // TODO(hclam): Add tests for data conversation in low latency mode. | 354 // TODO(hclam): Add tests for data conversation in low latency mode. |
| 420 | 355 |
| 421 } // namespace content | 356 } // namespace content |
| OLD | NEW |