Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(508)

Side by Side Diff: content/browser/renderer_host/media/audio_renderer_host_unittest.cc

Issue 2424163004: Factor out authorization from AudioRendererHost. (Closed)
Patch Set: Rename things. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/macros.h" 13 #include "base/macros.h"
14 #include "base/run_loop.h" 14 #include "base/run_loop.h"
15 #include "base/sync_socket.h" 15 #include "base/sync_socket.h"
16 #include "content/browser/media/capture/audio_mirroring_manager.h" 16 #include "content/browser/media/capture/audio_mirroring_manager.h"
17 #include "content/browser/media/media_internals.h" 17 #include "content/browser/media/media_internals.h"
18 #include "content/browser/renderer_host/media/audio_input_device_manager.h" 18 #include "content/browser/renderer_host/media/audio_input_device_manager.h"
19 #include "content/browser/renderer_host/media/media_stream_manager.h" 19 #include "content/browser/renderer_host/media/media_stream_manager.h"
20 #include "content/common/media/audio_messages.h" 20 #include "content/common/media/audio_messages.h"
21 #include "content/public/browser/media_device_id.h"
21 #include "content/public/common/content_switches.h" 22 #include "content/public/common/content_switches.h"
23 #include "content/public/test/mock_render_process_host.h"
24 #include "content/public/test/test_browser_context.h"
22 #include "content/public/test/test_browser_thread_bundle.h" 25 #include "content/public/test/test_browser_thread_bundle.h"
23 #include "ipc/ipc_message_utils.h" 26 #include "ipc/ipc_message_utils.h"
24 #include "media/audio/audio_manager.h" 27 #include "media/audio/fake_audio_log_factory.h"
28 #include "media/audio/fake_audio_manager.h"
25 #include "media/base/bind_to_current_loop.h" 29 #include "media/base/bind_to_current_loop.h"
26 #include "media/base/media_switches.h" 30 #include "media/base/media_switches.h"
27 #include "testing/gmock/include/gmock/gmock.h" 31 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h" 32 #include "testing/gtest/include/gtest/gtest.h"
29 33
30 using ::testing::_; 34 using ::testing::_;
31 using ::testing::Assign; 35 using ::testing::Assign;
32 using ::testing::AtLeast; 36 using ::testing::AtLeast;
33 using ::testing::DoAll; 37 using ::testing::DoAll;
34 using ::testing::NotNull; 38 using ::testing::NotNull;
35 39
36 namespace content { 40 namespace content {
37 41
38 namespace { 42 namespace {
39 const int kRenderProcessId = 1;
40 const int kRenderFrameId = 5; 43 const int kRenderFrameId = 5;
41 const int kStreamId = 50; 44 const int kStreamId = 50;
42 const char kSecurityOrigin[] = "http://localhost"; 45 const char kSecurityOrigin[] = "http://localhost";
43 const char kBadSecurityOrigin[] = "about:about"; 46 const char kBadSecurityOrigin[] = "about:about";
44 const char kDefaultDeviceId[] = ""; 47 const char kDefaultDeviceId[] = "";
48 const char kSalt[] = "salt";
45 const char kNondefaultDeviceId[] = 49 const char kNondefaultDeviceId[] =
46 "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"; 50 "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
47 const char kBadDeviceId[] = 51 const char kBadDeviceId[] =
48 "badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad1"; 52 "badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad1";
49 const char kInvalidDeviceId[] = "invalid-device-id"; 53 const char kInvalidDeviceId[] = "invalid-device-id";
50 54
51 void ValidateRenderFrameId(int render_process_id, 55 void ValidateRenderFrameId(int render_process_id,
52 int render_frame_id, 56 int render_frame_id,
53 const base::Callback<void(bool)>& callback) { 57 const base::Callback<void(bool)>& callback) {
54 DCHECK_CURRENTLY_ON(BrowserThread::UI); 58 DCHECK_CURRENTLY_ON(BrowserThread::UI);
55 const bool frame_exists = (render_process_id == kRenderProcessId && 59 const bool frame_exists = (render_frame_id == kRenderFrameId);
56 render_frame_id == kRenderFrameId);
57 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 60 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
58 base::Bind(callback, frame_exists)); 61 base::Bind(callback, frame_exists));
59 } 62 }
60 63
61 } // namespace
62 64
63 class MockAudioMirroringManager : public AudioMirroringManager { 65 class MockAudioMirroringManager : public AudioMirroringManager {
64 public: 66 public:
65 MockAudioMirroringManager() {} 67 MockAudioMirroringManager() {}
66 virtual ~MockAudioMirroringManager() {} 68 virtual ~MockAudioMirroringManager() {}
67 69
68 MOCK_METHOD3(AddDiverter, 70 MOCK_METHOD3(AddDiverter,
69 void(int render_process_id, 71 void(int render_process_id,
70 int render_frame_id, 72 int render_frame_id,
71 Diverter* diverter)); 73 Diverter* diverter));
72 MOCK_METHOD1(RemoveDiverter, void(Diverter* diverter)); 74 MOCK_METHOD1(RemoveDiverter, void(Diverter* diverter));
73 75
74 private: 76 private:
75 DISALLOW_COPY_AND_ASSIGN(MockAudioMirroringManager); 77 DISALLOW_COPY_AND_ASSIGN(MockAudioMirroringManager);
76 }; 78 };
77 79
80 class MockRenderProcessHostWithSignaling : public MockRenderProcessHost {
81 public:
82 MockRenderProcessHostWithSignaling(BrowserContext* context,
83 base::RunLoop* auth_run_loop)
84 : MockRenderProcessHost(context), auth_run_loop_(auth_run_loop) {}
85
86 void ShutdownForBadMessage(CrashReportMode crash_report_mode) override {
87 MockRenderProcessHost::ShutdownForBadMessage(crash_report_mode);
88 auth_run_loop_->Quit();
89 }
90
91 private:
92 base::RunLoop* auth_run_loop_;
93 };
94
95 class FakeAudioManagerWithAssociations : public media::FakeAudioManager {
96 public:
97 FakeAudioManagerWithAssociations(
98 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
99 media::AudioLogFactory* factory)
100 : FakeAudioManager(task_runner, task_runner, factory) {}
101
102 void CreateDeviceAssociation(const std::string& input_device_id,
103 const std::string& output_device_id) {
104 // We shouldn't accidentally add hashed ids, since the audio manager
105 // works with raw ids.
106 EXPECT_FALSE(IsValidDeviceId(input_device_id));
107 EXPECT_FALSE(IsValidDeviceId(output_device_id));
108
109 associations_[input_device_id] = output_device_id;
110 }
111
112 std::string GetAssociatedOutputDeviceID(
113 const std::string& input_id) override {
114 auto it = associations_.find(input_id);
115 return it == associations_.end() ? "" : it->second;
116 }
117
118 private:
119 std::map<std::string, std::string> associations_;
120 };
121
122 } // namespace
123
78 class MockAudioRendererHost : public AudioRendererHost { 124 class MockAudioRendererHost : public AudioRendererHost {
79 public: 125 public:
80 MockAudioRendererHost(base::RunLoop* auth_run_loop, 126 MockAudioRendererHost(base::RunLoop* auth_run_loop,
127 int render_process_id,
81 media::AudioManager* audio_manager, 128 media::AudioManager* audio_manager,
82 AudioMirroringManager* mirroring_manager, 129 AudioMirroringManager* mirroring_manager,
83 MediaInternals* media_internals, 130 MediaInternals* media_internals,
84 MediaStreamManager* media_stream_manager, 131 MediaStreamManager* media_stream_manager,
85 const std::string& salt) 132 const std::string& salt)
86 : AudioRendererHost(kRenderProcessId, 133 : AudioRendererHost(render_process_id,
87 audio_manager, 134 audio_manager,
88 mirroring_manager, 135 mirroring_manager,
89 media_internals, 136 media_internals,
90 media_stream_manager, 137 media_stream_manager,
91 salt), 138 salt),
92 shared_memory_length_(0), 139 shared_memory_length_(0),
93 auth_run_loop_(auth_run_loop) { 140 auth_run_loop_(auth_run_loop) {
94 set_render_frame_id_validate_function_for_testing(&ValidateRenderFrameId); 141 set_render_frame_id_validate_function_for_testing(&ValidateRenderFrameId);
95 } 142 }
96 143
97 // A list of mock methods. 144 // A list of mock methods.
98 MOCK_METHOD0(ShutdownForBadMessage, void());
99 MOCK_METHOD4(OnDeviceAuthorized, 145 MOCK_METHOD4(OnDeviceAuthorized,
100 void(int stream_id, 146 void(int stream_id,
101 media::OutputDeviceStatus device_status, 147 media::OutputDeviceStatus device_status,
102 const media::AudioParameters& output_params, 148 const media::AudioParameters& output_params,
103 const std::string& matched_device_id)); 149 const std::string& matched_device_id));
104 MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length)); 150 MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length));
105 MOCK_METHOD1(OnStreamError, void(int stream_id)); 151 MOCK_METHOD1(OnStreamError, void(int stream_id));
106 152
153 void ShutdownForBadMessage() override { bad_msg_count++; }
154
155 int bad_msg_count = 0;
156
107 private: 157 private:
108 virtual ~MockAudioRendererHost() { 158 virtual ~MockAudioRendererHost() {
109 // Make sure all audio streams have been deleted. 159 // Make sure all audio streams have been deleted.
110 EXPECT_TRUE(audio_entries_.empty()); 160 EXPECT_TRUE(audio_entries_.empty());
111 } 161 }
112 162
113 // This method is used to dispatch IPC messages to the renderer. We intercept 163 // This method is used to dispatch IPC messages to the renderer. We intercept
114 // these messages here and dispatch to our mock methods to verify the 164 // these messages here and dispatch to our mock methods to verify the
115 // conversation between this object and the renderer. 165 // conversation between this object and the renderer.
116 // Note: this means that file descriptors won't be duplicated, 166 // Note: this means that file descriptors won't be duplicated,
117 // leading to double-close errors from SyncSocket. 167 // leading to double-close errors from SyncSocket.
118 // See crbug.com/647659. 168 // See crbug.com/647659.
119 virtual bool Send(IPC::Message* message) { 169 bool Send(IPC::Message* message) override {
120 CHECK(message); 170 CHECK(message);
121 171
122 // In this method we dispatch the messages to the according handlers as if 172 // In this method we dispatch the messages to the according handlers as if
123 // we are the renderer. 173 // we are the renderer.
124 bool handled = true; 174 bool handled = true;
125 IPC_BEGIN_MESSAGE_MAP(MockAudioRendererHost, *message) 175 IPC_BEGIN_MESSAGE_MAP(MockAudioRendererHost, *message)
126 IPC_MESSAGE_HANDLER(AudioMsg_NotifyDeviceAuthorized, 176 IPC_MESSAGE_HANDLER(AudioMsg_NotifyDeviceAuthorized,
127 OnNotifyDeviceAuthorized) 177 OnNotifyDeviceAuthorized)
128 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamCreated, 178 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamCreated,
129 OnNotifyStreamCreated) 179 OnNotifyStreamCreated)
130 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamError, OnNotifyStreamError) 180 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamError, OnNotifyStreamError)
131 IPC_MESSAGE_UNHANDLED(handled = false) 181 IPC_MESSAGE_UNHANDLED(handled = false)
132 IPC_END_MESSAGE_MAP() 182 IPC_END_MESSAGE_MAP()
133 EXPECT_TRUE(handled); 183 EXPECT_TRUE(handled);
134 184
135 delete message; 185 delete message;
136 return true; 186 return true;
137 } 187 }
138 188
139 void OnNotifyDeviceAuthorized(int stream_id, 189 void OnNotifyDeviceAuthorized(int stream_id,
140 media::OutputDeviceStatus device_status, 190 media::OutputDeviceStatus device_status,
141 const media::AudioParameters& output_params, 191 const media::AudioParameters& output_params,
142 const std::string& matched_device_id) { 192 const std::string& matched_device_id) {
193 // Make sure we didn't leak a raw device id.
194 EXPECT_TRUE(IsValidDeviceId(matched_device_id));
195
143 OnDeviceAuthorized(stream_id, device_status, output_params, 196 OnDeviceAuthorized(stream_id, device_status, output_params,
144 matched_device_id); 197 matched_device_id);
145 auth_run_loop_->Quit(); 198 auth_run_loop_->Quit();
146 } 199 }
147 200
148 void OnNotifyStreamCreated( 201 void OnNotifyStreamCreated(
149 int stream_id, 202 int stream_id,
150 base::SharedMemoryHandle handle, 203 base::SharedMemoryHandle handle,
151 base::SyncSocket::TransitDescriptor socket_descriptor, 204 base::SyncSocket::TransitDescriptor socket_descriptor,
152 uint32_t length) { 205 uint32_t length) {
(...skipping 17 matching lines...) Expand all
170 std::unique_ptr<base::SharedMemory> shared_memory_; 223 std::unique_ptr<base::SharedMemory> shared_memory_;
171 std::unique_ptr<base::SyncSocket> sync_socket_; 224 std::unique_ptr<base::SyncSocket> sync_socket_;
172 uint32_t shared_memory_length_; 225 uint32_t shared_memory_length_;
173 base::RunLoop* auth_run_loop_; // Used to wait for authorization. 226 base::RunLoop* auth_run_loop_; // Used to wait for authorization.
174 227
175 DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost); 228 DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost);
176 }; 229 };
177 230
178 class AudioRendererHostTest : public testing::Test { 231 class AudioRendererHostTest : public testing::Test {
179 public: 232 public:
180 AudioRendererHostTest() { 233 AudioRendererHostTest()
181 audio_manager_ = media::AudioManager::CreateForTesting( 234 : log_factory(base::MakeUnique<media::FakeAudioLogFactory>()),
182 base::ThreadTaskRunnerHandle::Get()); 235 audio_manager_(base::MakeUnique<FakeAudioManagerWithAssociations>(
236 base::ThreadTaskRunnerHandle::Get(),
237 log_factory.get())),
238 render_process_host_(&browser_context_, &auth_run_loop_) {
183 base::CommandLine::ForCurrentProcess()->AppendSwitch( 239 base::CommandLine::ForCurrentProcess()->AppendSwitch(
184 switches::kUseFakeDeviceForMediaStream); 240 switches::kUseFakeDeviceForMediaStream);
185 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); 241 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
186 host_ = new MockAudioRendererHost( 242 host_ = new MockAudioRendererHost(
187 &auth_run_loop_, audio_manager_.get(), &mirroring_manager_, 243 &auth_run_loop_, render_process_host_.GetID(), audio_manager_.get(),
188 MediaInternals::GetInstance(), media_stream_manager_.get(), 244 &mirroring_manager_, MediaInternals::GetInstance(),
189 std::string()); 245 media_stream_manager_.get(), kSalt);
190
191 EXPECT_CALL(*host_, ShutdownForBadMessage()).Times(0);
192 246
193 // Simulate IPC channel connected. 247 // Simulate IPC channel connected.
194 host_->set_peer_process_for_testing(base::Process::Current()); 248 host_->set_peer_process_for_testing(base::Process::Current());
195 } 249 }
196 250
197 ~AudioRendererHostTest() override { 251 ~AudioRendererHostTest() override {
198 // Simulate closing the IPC channel and give the audio thread time to close 252 // Simulate closing the IPC channel and give the audio thread time to close
199 // the underlying streams. 253 // the underlying streams.
200 host_->OnChannelClosing(); 254 host_->OnChannelClosing();
201 SyncWithAudioThread(); 255 SyncWithAudioThread();
256 // To correctly clean up the audio manager, we first put it in a
257 // ScopedAudioManagerPtr. It will immediately destruct, cleaning up the
o1ka 2016/11/16 15:11:28 well, not "immediately", but when scoped ptr goes
Max Morin 2016/11/16 15:54:36 The ScoperAudioManagerPtr is temporary (not assign
o1ka 2016/11/16 16:05:46 Right, I missed that. Thanks for clarification!
258 // audio manager correctly.
259 media::ScopedAudioManagerPtr(audio_manager_.release());
202 260
203 // Release the reference to the mock object. The object will be destructed 261 // Release the reference to the mock object. The object will be destructed
204 // on message_loop_. 262 // on message_loop_.
205 host_ = NULL; 263 host_ = nullptr;
206 } 264 }
207 265
208 protected: 266 protected:
209 void Create() { 267 void OverrideDevicePermissions(bool has_permissions) {
210 Create(false, kDefaultDeviceId, url::Origin(GURL(kSecurityOrigin)), true); 268 host_->OverrideDevicePermissionsForTesting(has_permissions);
211 } 269 }
212 270
213 void Create(bool unified_stream, 271 std::string GetNondefaultIdExpectedToPassPermissionsCheck() {
214 const std::string& device_id, 272 std::string nondefault_id;
273
274 MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
275 devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
276 media_stream_manager_->media_devices_manager()->EnumerateDevices(
277 devices_to_enumerate,
278 base::Bind(
279 [](std::string* out, const MediaDeviceEnumeration& result) {
280 // Index 0 is default, so use 1. Always exists because we use
281 // fake devices.
282 CHECK(result[MediaDeviceType::MEDIA_DEVICE_TYPE_AUDIO_OUTPUT]
283 .size() > 1)
284 << "Expected to have a nondefault device.";
285 *out = result[MediaDeviceType::MEDIA_DEVICE_TYPE_AUDIO_OUTPUT][1]
286 .device_id;
287 },
288 base::Unretained(&nondefault_id)));
289
290 // Make sure nondefault_id is set before returning.
291 base::RunLoop().RunUntilIdle();
292
293 return nondefault_id;
294 }
295
296 std::string GetNondefaultInputId() {
297 std::string nondefault_id;
298
299 MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
300 devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = true;
301 media_stream_manager_->media_devices_manager()->EnumerateDevices(
302 devices_to_enumerate,
303 base::Bind(
304 // Index 0 is default, so use 1. Always exists because we use
305 // fake devices.
306 [](std::string* out, const MediaDeviceEnumeration& result) {
307 CHECK(result[MediaDeviceType::MEDIA_DEVICE_TYPE_AUDIO_INPUT]
308 .size() > 1)
309 << "Expected to have a nondefault device.";
310 *out = result[MediaDeviceType::MEDIA_DEVICE_TYPE_AUDIO_INPUT][1]
311 .device_id;
312 },
313 base::Unretained(&nondefault_id)));
314
315 base::RunLoop().RunUntilIdle();
316
317 return nondefault_id;
318 }
319
320 void Create() {
321 Create(kDefaultDeviceId, url::Origin(GURL(kSecurityOrigin)), true, true);
322 }
323
324 void Create(const std::string& device_id,
215 const url::Origin& security_origin, 325 const url::Origin& security_origin,
216 bool wait_for_auth) { 326 bool wait_for_auth,
327 bool expect_onauthorized) {
217 media::OutputDeviceStatus expected_device_status = 328 media::OutputDeviceStatus expected_device_status =
218 device_id == kDefaultDeviceId 329 device_id == kDefaultDeviceId ||
330 device_id ==
331 MediaStreamManager::GetHMACForMediaDeviceID(
332 kSalt, url::Origin(GURL(kSecurityOrigin)),
333 GetNondefaultIdExpectedToPassPermissionsCheck())
219 ? media::OUTPUT_DEVICE_STATUS_OK 334 ? media::OUTPUT_DEVICE_STATUS_OK
220 : device_id == kBadDeviceId 335 : device_id == kBadDeviceId
221 ? media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED 336 ? media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED
222 : media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND; 337 : media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND;
223 338
224 EXPECT_CALL(*host_.get(), 339 if (expect_onauthorized)
225 OnDeviceAuthorized(kStreamId, expected_device_status, _, _)); 340 EXPECT_CALL(*host_.get(),
341 OnDeviceAuthorized(kStreamId, expected_device_status, _, _));
226 342
227 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) { 343 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) {
228 EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _)); 344 EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _));
229 EXPECT_CALL(mirroring_manager_, 345 EXPECT_CALL(mirroring_manager_, AddDiverter(render_process_host_.GetID(),
230 AddDiverter(kRenderProcessId, kRenderFrameId, NotNull())) 346 kRenderFrameId, NotNull()))
231 .RetiresOnSaturation(); 347 .RetiresOnSaturation();
232 } 348 }
233 349
234 // Send a create stream message to the audio output stream and wait until 350 // Send a create stream message to the audio output stream and wait until
235 // we receive the created message. 351 // we receive the created message.
236 media::AudioParameters params( 352 media::AudioParameters params(
237 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO, 353 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO,
238 media::AudioParameters::kAudioCDSampleRate, 16, 354 media::AudioParameters::kAudioCDSampleRate, 16,
239 media::AudioParameters::kAudioCDSampleRate / 10); 355 media::AudioParameters::kAudioCDSampleRate / 10);
240 int session_id = 0; 356 int session_id = 0;
241 if (unified_stream) { 357
242 // Use AudioInputDeviceManager::kFakeOpenSessionId as the session id to
243 // pass the permission check.
244 session_id = AudioInputDeviceManager::kFakeOpenSessionId;
245 }
246 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id, 358 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id,
247 device_id, security_origin); 359 device_id, security_origin);
248 if (wait_for_auth) 360 if (wait_for_auth)
249 auth_run_loop_.Run(); 361 auth_run_loop_.Run();
250 362
251 if (!wait_for_auth || 363 if (!wait_for_auth ||
252 expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) 364 expected_device_status == media::OUTPUT_DEVICE_STATUS_OK)
253 host_->OnCreateStream(kStreamId, kRenderFrameId, params); 365 host_->OnCreateStream(kStreamId, kRenderFrameId, params);
254 366
255 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) 367 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK)
256 // At some point in the future, a corresponding RemoveDiverter() call must 368 // At some point in the future, a corresponding RemoveDiverter() call must
257 // be made. 369 // be made.
258 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull())) 370 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()))
259 .RetiresOnSaturation(); 371 .RetiresOnSaturation();
260 SyncWithAudioThread(); 372 SyncWithAudioThread();
261 } 373 }
262 374
263 void RequestDeviceAuthorizationWithBadOrigin(const std::string& device_id) { 375 void RequestDeviceAuthorizationWithBadOrigin(const std::string& device_id) {
264 int session_id = 0; 376 int session_id = 0;
265 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id, 377 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id,
266 device_id, 378 device_id,
267 url::Origin(GURL(kBadSecurityOrigin))); 379 url::Origin(GURL(kBadSecurityOrigin)));
268 SyncWithAudioThread(); 380 SyncWithAudioThread();
269 } 381 }
270 382
271 void CreateWithoutWaitingForAuth(const std::string& device_id) { 383 void CreateWithoutWaitingForAuth(const std::string& device_id) {
272 Create(false, device_id, url::Origin(GURL(kSecurityOrigin)), false); 384 Create(device_id, url::Origin(GURL(kSecurityOrigin)), false, false);
273 } 385 }
274 386
275 void CreateWithInvalidRenderFrameId() { 387 void CreateWithInvalidRenderFrameId() {
276 // When creating a stream with an invalid render frame ID, the host will 388 // When creating a stream with an invalid render frame ID, the host will
277 // reply with a stream error message. 389 // reply with a stream error message.
278 EXPECT_CALL(*host_, OnStreamError(kStreamId)); 390 EXPECT_CALL(*host_, OnStreamError(kStreamId));
279 391
280 // However, validation does not block stream creation, so these method calls 392 // However, validation does not block stream creation, so these method calls
281 // might be made: 393 // might be made:
282 EXPECT_CALL(*host_, OnStreamCreated(kStreamId, _)).Times(AtLeast(0)); 394 EXPECT_CALL(*host_, OnStreamCreated(kStreamId, _)).Times(AtLeast(0));
283 EXPECT_CALL(mirroring_manager_, AddDiverter(_, _, _)).Times(AtLeast(0)); 395 EXPECT_CALL(mirroring_manager_, AddDiverter(_, _, _)).Times(AtLeast(0));
284 EXPECT_CALL(mirroring_manager_, RemoveDiverter(_)).Times(AtLeast(0)); 396 EXPECT_CALL(mirroring_manager_, RemoveDiverter(_)).Times(AtLeast(0));
285 397
286 // Provide a seemingly-valid render frame ID; and it should be rejected when 398 // Provide a seemingly-valid render frame ID; and it should be rejected when
287 // AudioRendererHost calls ValidateRenderFrameId(). 399 // AudioRendererHost calls ValidateRenderFrameId().
288 const int kInvalidRenderFrameId = kRenderFrameId + 1; 400 const int kInvalidRenderFrameId = kRenderFrameId + 1;
289 const media::AudioParameters params( 401 const media::AudioParameters params(
290 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO, 402 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO,
291 media::AudioParameters::kAudioCDSampleRate, 16, 403 media::AudioParameters::kAudioCDSampleRate, 16,
292 media::AudioParameters::kAudioCDSampleRate / 10); 404 media::AudioParameters::kAudioCDSampleRate / 10);
293 host_->OnCreateStream(kStreamId, kInvalidRenderFrameId, params); 405 host_->OnCreateStream(kStreamId, kInvalidRenderFrameId, params);
294 base::RunLoop().RunUntilIdle(); 406 base::RunLoop().RunUntilIdle();
295 } 407 }
296 408
409 void CreateUnifiedStream(const url::Origin& security_origin) {
410 std::string output_id = GetNondefaultIdExpectedToPassPermissionsCheck();
411 std::string input_id = GetNondefaultInputId();
412 std::string hashed_output_id = MediaStreamManager::GetHMACForMediaDeviceID(
413 kSalt, url::Origin(GURL(kSecurityOrigin)), output_id);
414 // Set up association between input and output so that the output
415 // device gets selected when using session id:
416 audio_manager_->CreateDeviceAssociation(input_id, output_id);
417 int session_id = media_stream_manager_->audio_input_device_manager()->Open(
418 StreamDeviceInfo(MEDIA_DEVICE_AUDIO_CAPTURE, "Fake input device",
419 input_id));
420 base::RunLoop().RunUntilIdle();
421
422 // Send a create stream message to the audio output stream and wait until
423 // we receive the created message.
424 media::AudioParameters params(
425 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO,
426 media::AudioParameters::kAudioCDSampleRate, 16,
427 media::AudioParameters::kAudioCDSampleRate / 10);
428
429 EXPECT_CALL(*host_.get(),
430 OnDeviceAuthorized(kStreamId, media::OUTPUT_DEVICE_STATUS_OK, _,
431 hashed_output_id))
432 .Times(1);
433 EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _));
434 EXPECT_CALL(mirroring_manager_, AddDiverter(render_process_host_.GetID(),
435 kRenderFrameId, NotNull()))
436 .RetiresOnSaturation();
437 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()))
438 .RetiresOnSaturation();
439
440 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id,
441 /*device id*/ std::string(),
442 security_origin);
443
444 auth_run_loop_.Run();
445
446 host_->OnCreateStream(kStreamId, kRenderFrameId, params);
447
448 SyncWithAudioThread();
449 }
450
297 void Close() { 451 void Close() {
298 // Send a message to AudioRendererHost to tell it we want to close the 452 // Send a message to AudioRendererHost to tell it we want to close the
299 // stream. 453 // stream.
300 host_->OnCloseStream(kStreamId); 454 host_->OnCloseStream(kStreamId);
301 SyncWithAudioThread(); 455 SyncWithAudioThread();
302 } 456 }
303 457
304 void Play() { 458 void Play() {
305 host_->OnPlayStream(kStreamId); 459 host_->OnPlayStream(kStreamId);
306 SyncWithAudioThread(); 460 SyncWithAudioThread();
(...skipping 30 matching lines...) Expand all
337 // closing an audio stream. 491 // closing an audio stream.
338 void SyncWithAudioThread() { 492 void SyncWithAudioThread() {
339 base::RunLoop().RunUntilIdle(); 493 base::RunLoop().RunUntilIdle();
340 494
341 base::RunLoop run_loop; 495 base::RunLoop run_loop;
342 audio_manager_->GetTaskRunner()->PostTask( 496 audio_manager_->GetTaskRunner()->PostTask(
343 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure())); 497 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure()));
344 run_loop.Run(); 498 run_loop.Run();
345 } 499 }
346 500
347 void ExpectShutdown() { 501 void AssertBadMsgReported() {
348 EXPECT_CALL(*host_, ShutdownForBadMessage()).Times(1); 502 // Bad messages can be reported either directly to the RPH or through the
503 // ARH, so we check both of them.
504 EXPECT_EQ(render_process_host_.bad_msg_count() + host_->bad_msg_count, 1);
349 } 505 }
350 506
351 private: 507 private:
352 // MediaStreamManager uses a DestructionObserver, so it must outlive the 508 // MediaStreamManager uses a DestructionObserver, so it must outlive the
353 // TestBrowserThreadBundle. 509 // TestBrowserThreadBundle.
354 std::unique_ptr<MediaStreamManager> media_stream_manager_; 510 std::unique_ptr<MediaStreamManager> media_stream_manager_;
355 TestBrowserThreadBundle thread_bundle_; 511 TestBrowserThreadBundle thread_bundle_;
356 media::ScopedAudioManagerPtr audio_manager_; 512 TestBrowserContext browser_context_;
513 std::unique_ptr<media::FakeAudioLogFactory> log_factory;
514 std::unique_ptr<FakeAudioManagerWithAssociations> audio_manager_;
357 MockAudioMirroringManager mirroring_manager_; 515 MockAudioMirroringManager mirroring_manager_;
516 base::RunLoop auth_run_loop_;
517 MockRenderProcessHostWithSignaling render_process_host_;
358 scoped_refptr<MockAudioRendererHost> host_; 518 scoped_refptr<MockAudioRendererHost> host_;
359 base::RunLoop auth_run_loop_;
360 519
361 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest); 520 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest);
362 }; 521 };
363 522
364 TEST_F(AudioRendererHostTest, CreateAndClose) { 523 TEST_F(AudioRendererHostTest, CreateAndClose) {
365 Create(); 524 Create();
366 Close(); 525 Close();
367 } 526 }
368 527
369 // Simulate the case where a stream is not properly closed. 528 // Simulate the case where a stream is not properly closed.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 // the audio device is closed but the render process try to close the 574 // the audio device is closed but the render process try to close the
416 // audio stream again. 575 // audio stream again.
417 TEST_F(AudioRendererHostTest, SimulateErrorAndClose) { 576 TEST_F(AudioRendererHostTest, SimulateErrorAndClose) {
418 Create(); 577 Create();
419 Play(); 578 Play();
420 SimulateError(); 579 SimulateError();
421 Close(); 580 Close();
422 } 581 }
423 582
424 TEST_F(AudioRendererHostTest, CreateUnifiedStreamAndClose) { 583 TEST_F(AudioRendererHostTest, CreateUnifiedStreamAndClose) {
425 Create(true, kDefaultDeviceId, url::Origin(GURL(kSecurityOrigin)), true); 584 CreateUnifiedStream(url::Origin(GURL(kSecurityOrigin)));
426 Close(); 585 Close();
427 } 586 }
428 587
429 TEST_F(AudioRendererHostTest, CreateUnauthorizedDevice) { 588 TEST_F(AudioRendererHostTest, CreateUnauthorizedDevice) {
430 Create(false, kBadDeviceId, url::Origin(GURL(kSecurityOrigin)), true); 589 Create(kBadDeviceId, url::Origin(GURL(kSecurityOrigin)), true, true);
590 Close();
591 }
592
593 TEST_F(AudioRendererHostTest, CreateAuthorizedDevice) {
594 OverrideDevicePermissions(true);
595 std::string id = GetNondefaultIdExpectedToPassPermissionsCheck();
596 std::string hashed_id = MediaStreamManager::GetHMACForMediaDeviceID(
597 kSalt, url::Origin(GURL(kSecurityOrigin)), id);
598 Create(hashed_id, url::Origin(GURL(kSecurityOrigin)), true, true);
431 Close(); 599 Close();
432 } 600 }
433 601
434 TEST_F(AudioRendererHostTest, CreateDeviceWithAuthorizationPendingIsError) { 602 TEST_F(AudioRendererHostTest, CreateDeviceWithAuthorizationPendingIsError) {
435 ExpectShutdown();
436 CreateWithoutWaitingForAuth(kBadDeviceId); 603 CreateWithoutWaitingForAuth(kBadDeviceId);
437 Close(); 604 Close();
605 AssertBadMsgReported();
438 } 606 }
439 607
440 TEST_F(AudioRendererHostTest, CreateDeviceWithBadSecurityOrigin) { 608 TEST_F(AudioRendererHostTest, CreateDeviceWithBadSecurityOrigin) {
441 ExpectShutdown();
442 RequestDeviceAuthorizationWithBadOrigin(kNondefaultDeviceId); 609 RequestDeviceAuthorizationWithBadOrigin(kNondefaultDeviceId);
443 Close(); 610 Close();
611 AssertBadMsgReported();
444 } 612 }
445 613
446 TEST_F(AudioRendererHostTest, CreateInvalidDevice) { 614 TEST_F(AudioRendererHostTest, CreateInvalidDevice) {
447 Create(false, kInvalidDeviceId, url::Origin(GURL(kSecurityOrigin)), true); 615 Create(kInvalidDeviceId, url::Origin(GURL(kSecurityOrigin)), true, false);
448 Close(); 616 Close();
617 AssertBadMsgReported();
449 } 618 }
450 619
451 TEST_F(AudioRendererHostTest, CreateFailsForInvalidRenderFrame) { 620 TEST_F(AudioRendererHostTest, CreateFailsForInvalidRenderFrame) {
452 CreateWithInvalidRenderFrameId(); 621 CreateWithInvalidRenderFrameId();
453 Close(); 622 Close();
454 } 623 }
455 624
456 // TODO(hclam): Add tests for data conversation in low latency mode. 625 // TODO(hclam): Add tests for data conversation in low latency mode.
457 626
458 } // namespace content 627 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698