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

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

Issue 2424163004: Factor out authorization from AudioRendererHost. (Closed)
Patch Set: . 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();
202 256
203 // Release the reference to the mock object. The object will be destructed 257 // Release the reference to the mock object. The object will be destructed
204 // on message_loop_. 258 // on message_loop_.
205 host_ = NULL; 259 host_ = NULL;
206 } 260 }
207 261
208 protected: 262 protected:
209 void Create() { 263 void OverrideDevicePermissions(bool has_permissions) {
210 Create(false, kDefaultDeviceId, url::Origin(GURL(kSecurityOrigin)), true); 264 host_->OverrideDevicePermissionsForTesting(has_permissions);
211 } 265 }
212 266
213 void Create(bool unified_stream, 267 std::string GetNondefaultIdExpectedToPassPermissionsCheck() {
214 const std::string& device_id, 268 std::string nondefault_id;
269
270 MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
271 devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_OUTPUT] = true;
272 media_stream_manager_->media_devices_manager()->EnumerateDevices(
273 devices_to_enumerate,
274 base::Bind(
275 [](std::string* out, const MediaDeviceEnumeration& result) {
276 // Index 0 is default, so use 1. Always exists because we use
277 // fake devices.
278 CHECK(result[MediaDeviceType::MEDIA_DEVICE_TYPE_AUDIO_OUTPUT]
279 .size() > 1)
280 << "Expected to have a nondefault device.";
281 *out = result[MediaDeviceType::MEDIA_DEVICE_TYPE_AUDIO_OUTPUT][1]
282 .device_id;
283 },
284 base::Unretained(&nondefault_id)));
285
286 // Make sure nondefault_id is set before returning.
287 base::RunLoop().RunUntilIdle();
288
289 return nondefault_id;
290 }
291
292 std::string GetNondefaultInputId() {
293 std::string nondefault_id;
294
295 MediaDevicesManager::BoolDeviceTypes devices_to_enumerate;
296 devices_to_enumerate[MEDIA_DEVICE_TYPE_AUDIO_INPUT] = true;
297 media_stream_manager_->media_devices_manager()->EnumerateDevices(
298 devices_to_enumerate,
299 base::Bind(
300 // Index 0 is default, so use 1. Always exists because we use
301 // fake devices.
302 [](std::string* out, const MediaDeviceEnumeration& result) {
303 CHECK(result[MediaDeviceType::MEDIA_DEVICE_TYPE_AUDIO_INPUT]
304 .size() > 1)
305 << "Expected to have a nondefault device.";
306 *out = result[MediaDeviceType::MEDIA_DEVICE_TYPE_AUDIO_INPUT][1]
307 .device_id;
308 },
309 base::Unretained(&nondefault_id)));
310
311 base::RunLoop().RunUntilIdle();
312
313 return nondefault_id;
314 }
315
316 void Create() {
317 Create(kDefaultDeviceId, url::Origin(GURL(kSecurityOrigin)), true, true);
318 }
319
320 void Create(const std::string& device_id,
215 const url::Origin& security_origin, 321 const url::Origin& security_origin,
216 bool wait_for_auth) { 322 bool wait_for_auth,
323 bool expect_onauthorized) {
217 media::OutputDeviceStatus expected_device_status = 324 media::OutputDeviceStatus expected_device_status =
218 device_id == kDefaultDeviceId 325 device_id == kDefaultDeviceId ||
326 device_id ==
327 MediaStreamManager::GetHMACForMediaDeviceID(
328 kSalt, url::Origin(GURL(kSecurityOrigin)),
329 GetNondefaultIdExpectedToPassPermissionsCheck())
219 ? media::OUTPUT_DEVICE_STATUS_OK 330 ? media::OUTPUT_DEVICE_STATUS_OK
220 : device_id == kBadDeviceId 331 : device_id == kBadDeviceId
221 ? media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED 332 ? media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED
222 : media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND; 333 : media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND;
223 334
224 EXPECT_CALL(*host_.get(), 335 if (expect_onauthorized)
225 OnDeviceAuthorized(kStreamId, expected_device_status, _, _)); 336 EXPECT_CALL(*host_.get(),
337 OnDeviceAuthorized(kStreamId, expected_device_status, _, _));
226 338
227 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) { 339 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) {
228 EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _)); 340 EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _));
229 EXPECT_CALL(mirroring_manager_, 341 EXPECT_CALL(mirroring_manager_, AddDiverter(render_process_host_.GetID(),
230 AddDiverter(kRenderProcessId, kRenderFrameId, NotNull())) 342 kRenderFrameId, NotNull()))
231 .RetiresOnSaturation(); 343 .RetiresOnSaturation();
232 } 344 }
233 345
234 // Send a create stream message to the audio output stream and wait until 346 // Send a create stream message to the audio output stream and wait until
235 // we receive the created message. 347 // we receive the created message.
236 media::AudioParameters params( 348 media::AudioParameters params(
237 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO, 349 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO,
238 media::AudioParameters::kAudioCDSampleRate, 16, 350 media::AudioParameters::kAudioCDSampleRate, 16,
239 media::AudioParameters::kAudioCDSampleRate / 10); 351 media::AudioParameters::kAudioCDSampleRate / 10);
240 int session_id = 0; 352 int session_id = 0;
241 if (unified_stream) { 353
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, 354 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id,
247 device_id, security_origin); 355 device_id, security_origin);
248 if (wait_for_auth) 356 if (wait_for_auth)
249 auth_run_loop_.Run(); 357 auth_run_loop_.Run();
250 358
251 if (!wait_for_auth || 359 if (!wait_for_auth ||
252 expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) 360 expected_device_status == media::OUTPUT_DEVICE_STATUS_OK)
253 host_->OnCreateStream(kStreamId, kRenderFrameId, params); 361 host_->OnCreateStream(kStreamId, kRenderFrameId, params);
254 362
255 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) 363 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK)
256 // At some point in the future, a corresponding RemoveDiverter() call must 364 // At some point in the future, a corresponding RemoveDiverter() call must
257 // be made. 365 // be made.
258 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull())) 366 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()))
259 .RetiresOnSaturation(); 367 .RetiresOnSaturation();
260 SyncWithAudioThread(); 368 SyncWithAudioThread();
261 } 369 }
262 370
263 void RequestDeviceAuthorizationWithBadOrigin(const std::string& device_id) { 371 void RequestDeviceAuthorizationWithBadOrigin(const std::string& device_id) {
264 int session_id = 0; 372 int session_id = 0;
265 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id, 373 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id,
266 device_id, 374 device_id,
267 url::Origin(GURL(kBadSecurityOrigin))); 375 url::Origin(GURL(kBadSecurityOrigin)));
268 SyncWithAudioThread(); 376 SyncWithAudioThread();
269 } 377 }
270 378
271 void CreateWithoutWaitingForAuth(const std::string& device_id) { 379 void CreateWithoutWaitingForAuth(const std::string& device_id) {
272 Create(false, device_id, url::Origin(GURL(kSecurityOrigin)), false); 380 Create(device_id, url::Origin(GURL(kSecurityOrigin)), false, false);
273 } 381 }
274 382
275 void CreateWithInvalidRenderFrameId() { 383 void CreateWithInvalidRenderFrameId() {
276 // When creating a stream with an invalid render frame ID, the host will 384 // When creating a stream with an invalid render frame ID, the host will
277 // reply with a stream error message. 385 // reply with a stream error message.
278 EXPECT_CALL(*host_, OnStreamError(kStreamId)); 386 EXPECT_CALL(*host_, OnStreamError(kStreamId));
279 387
280 // However, validation does not block stream creation, so these method calls 388 // However, validation does not block stream creation, so these method calls
281 // might be made: 389 // might be made:
282 EXPECT_CALL(*host_, OnStreamCreated(kStreamId, _)).Times(AtLeast(0)); 390 EXPECT_CALL(*host_, OnStreamCreated(kStreamId, _)).Times(AtLeast(0));
283 EXPECT_CALL(mirroring_manager_, AddDiverter(_, _, _)).Times(AtLeast(0)); 391 EXPECT_CALL(mirroring_manager_, AddDiverter(_, _, _)).Times(AtLeast(0));
284 EXPECT_CALL(mirroring_manager_, RemoveDiverter(_)).Times(AtLeast(0)); 392 EXPECT_CALL(mirroring_manager_, RemoveDiverter(_)).Times(AtLeast(0));
285 393
286 // Provide a seemingly-valid render frame ID; and it should be rejected when 394 // Provide a seemingly-valid render frame ID; and it should be rejected when
287 // AudioRendererHost calls ValidateRenderFrameId(). 395 // AudioRendererHost calls ValidateRenderFrameId().
288 const int kInvalidRenderFrameId = kRenderFrameId + 1; 396 const int kInvalidRenderFrameId = kRenderFrameId + 1;
289 const media::AudioParameters params( 397 const media::AudioParameters params(
290 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO, 398 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO,
291 media::AudioParameters::kAudioCDSampleRate, 16, 399 media::AudioParameters::kAudioCDSampleRate, 16,
292 media::AudioParameters::kAudioCDSampleRate / 10); 400 media::AudioParameters::kAudioCDSampleRate / 10);
293 host_->OnCreateStream(kStreamId, kInvalidRenderFrameId, params); 401 host_->OnCreateStream(kStreamId, kInvalidRenderFrameId, params);
294 base::RunLoop().RunUntilIdle(); 402 base::RunLoop().RunUntilIdle();
295 } 403 }
296 404
405 void CreateUnifiedStream(const url::Origin& security_origin) {
406 std::string output_id = GetNondefaultIdExpectedToPassPermissionsCheck();
407 std::string input_id = GetNondefaultInputId();
408 std::string hashed_output_id = MediaStreamManager::GetHMACForMediaDeviceID(
409 kSalt, url::Origin(GURL(kSecurityOrigin)), output_id);
410 // Set up association between input and output so that the output
411 // device gets selected when using session id:
412 audio_manager_->CreateDeviceAssociation(input_id, output_id);
413 int session_id = media_stream_manager_->audio_input_device_manager()->Open(
414 StreamDeviceInfo(MEDIA_DEVICE_AUDIO_CAPTURE, "Fake input device",
415 input_id));
416 base::RunLoop().RunUntilIdle();
417
418 // Send a create stream message to the audio output stream and wait until
419 // we receive the created message.
420 media::AudioParameters params(
421 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO,
422 media::AudioParameters::kAudioCDSampleRate, 16,
423 media::AudioParameters::kAudioCDSampleRate / 10);
424
425 EXPECT_CALL(*host_.get(),
426 OnDeviceAuthorized(kStreamId, media::OUTPUT_DEVICE_STATUS_OK, _,
427 hashed_output_id))
428 .Times(1);
429 EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _));
430 EXPECT_CALL(mirroring_manager_, AddDiverter(render_process_host_.GetID(),
431 kRenderFrameId, NotNull()))
432 .RetiresOnSaturation();
433 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()))
434 .RetiresOnSaturation();
435
436 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id,
437 /*device id*/ std::string(),
438 security_origin);
439
440 auth_run_loop_.Run();
441
442 host_->OnCreateStream(kStreamId, kRenderFrameId, params);
443
444 SyncWithAudioThread();
445 }
446
297 void Close() { 447 void Close() {
298 // Send a message to AudioRendererHost to tell it we want to close the 448 // Send a message to AudioRendererHost to tell it we want to close the
299 // stream. 449 // stream.
300 host_->OnCloseStream(kStreamId); 450 host_->OnCloseStream(kStreamId);
301 SyncWithAudioThread(); 451 SyncWithAudioThread();
302 } 452 }
303 453
304 void Play() { 454 void Play() {
305 host_->OnPlayStream(kStreamId); 455 host_->OnPlayStream(kStreamId);
306 SyncWithAudioThread(); 456 SyncWithAudioThread();
(...skipping 30 matching lines...) Expand all
337 // closing an audio stream. 487 // closing an audio stream.
338 void SyncWithAudioThread() { 488 void SyncWithAudioThread() {
339 base::RunLoop().RunUntilIdle(); 489 base::RunLoop().RunUntilIdle();
340 490
341 base::RunLoop run_loop; 491 base::RunLoop run_loop;
342 audio_manager_->GetTaskRunner()->PostTask( 492 audio_manager_->GetTaskRunner()->PostTask(
343 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure())); 493 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure()));
344 run_loop.Run(); 494 run_loop.Run();
345 } 495 }
346 496
347 void ExpectShutdown() { 497 void AssertBadMsgReported() {
348 EXPECT_CALL(*host_, ShutdownForBadMessage()).Times(1); 498 // Bad messages can be reported either directly to the RPH or through the
499 // ARH, so we check both of them.
500 EXPECT_EQ(render_process_host_.bad_msg_count() + host_->bad_msg_count, 1);
349 } 501 }
350 502
351 private: 503 private:
352 // MediaStreamManager uses a DestructionObserver, so it must outlive the 504 // MediaStreamManager uses a DestructionObserver, so it must outlive the
353 // TestBrowserThreadBundle. 505 // TestBrowserThreadBundle.
354 std::unique_ptr<MediaStreamManager> media_stream_manager_; 506 std::unique_ptr<MediaStreamManager> media_stream_manager_;
355 TestBrowserThreadBundle thread_bundle_; 507 TestBrowserThreadBundle thread_bundle_;
356 media::ScopedAudioManagerPtr audio_manager_; 508 TestBrowserContext browser_context_;
509 std::unique_ptr<media::FakeAudioLogFactory> log_factory;
510 std::unique_ptr<FakeAudioManagerWithAssociations> audio_manager_;
357 MockAudioMirroringManager mirroring_manager_; 511 MockAudioMirroringManager mirroring_manager_;
512 base::RunLoop auth_run_loop_;
513 MockRenderProcessHostWithSignaling render_process_host_;
358 scoped_refptr<MockAudioRendererHost> host_; 514 scoped_refptr<MockAudioRendererHost> host_;
359 base::RunLoop auth_run_loop_;
360 515
361 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest); 516 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest);
362 }; 517 };
363 518
364 TEST_F(AudioRendererHostTest, CreateAndClose) { 519 TEST_F(AudioRendererHostTest, CreateAndClose) {
365 Create(); 520 Create();
366 Close(); 521 Close();
367 } 522 }
368 523
369 // Simulate the case where a stream is not properly closed. 524 // 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 570 // the audio device is closed but the render process try to close the
416 // audio stream again. 571 // audio stream again.
417 TEST_F(AudioRendererHostTest, SimulateErrorAndClose) { 572 TEST_F(AudioRendererHostTest, SimulateErrorAndClose) {
418 Create(); 573 Create();
419 Play(); 574 Play();
420 SimulateError(); 575 SimulateError();
421 Close(); 576 Close();
422 } 577 }
423 578
424 TEST_F(AudioRendererHostTest, CreateUnifiedStreamAndClose) { 579 TEST_F(AudioRendererHostTest, CreateUnifiedStreamAndClose) {
425 Create(true, kDefaultDeviceId, url::Origin(GURL(kSecurityOrigin)), true); 580 CreateUnifiedStream(url::Origin(GURL(kSecurityOrigin)));
426 Close(); 581 Close();
427 } 582 }
428 583
429 TEST_F(AudioRendererHostTest, CreateUnauthorizedDevice) { 584 TEST_F(AudioRendererHostTest, CreateUnauthorizedDevice) {
430 Create(false, kBadDeviceId, url::Origin(GURL(kSecurityOrigin)), true); 585 Create(kBadDeviceId, url::Origin(GURL(kSecurityOrigin)), true, true);
586 Close();
587 }
588
589 TEST_F(AudioRendererHostTest, CreateAuthorizedDevice) {
590 OverrideDevicePermissions(true);
591 std::string id = GetNondefaultIdExpectedToPassPermissionsCheck();
592 std::string hashed_id = MediaStreamManager::GetHMACForMediaDeviceID(
593 kSalt, url::Origin(GURL(kSecurityOrigin)), id);
594 Create(hashed_id, url::Origin(GURL(kSecurityOrigin)), true, true);
431 Close(); 595 Close();
432 } 596 }
433 597
434 TEST_F(AudioRendererHostTest, CreateDeviceWithAuthorizationPendingIsError) { 598 TEST_F(AudioRendererHostTest, CreateDeviceWithAuthorizationPendingIsError) {
435 ExpectShutdown();
436 CreateWithoutWaitingForAuth(kBadDeviceId); 599 CreateWithoutWaitingForAuth(kBadDeviceId);
437 Close(); 600 Close();
601 AssertBadMsgReported();
438 } 602 }
439 603
440 TEST_F(AudioRendererHostTest, CreateDeviceWithBadSecurityOrigin) { 604 TEST_F(AudioRendererHostTest, CreateDeviceWithBadSecurityOrigin) {
441 ExpectShutdown();
442 RequestDeviceAuthorizationWithBadOrigin(kNondefaultDeviceId); 605 RequestDeviceAuthorizationWithBadOrigin(kNondefaultDeviceId);
443 Close(); 606 Close();
607 AssertBadMsgReported();
444 } 608 }
445 609
446 TEST_F(AudioRendererHostTest, CreateInvalidDevice) { 610 TEST_F(AudioRendererHostTest, CreateInvalidDevice) {
447 Create(false, kInvalidDeviceId, url::Origin(GURL(kSecurityOrigin)), true); 611 Create(kInvalidDeviceId, url::Origin(GURL(kSecurityOrigin)), true, false);
448 Close(); 612 Close();
613 AssertBadMsgReported();
449 } 614 }
450 615
451 TEST_F(AudioRendererHostTest, CreateFailsForInvalidRenderFrame) { 616 TEST_F(AudioRendererHostTest, CreateFailsForInvalidRenderFrame) {
452 CreateWithInvalidRenderFrameId(); 617 CreateWithInvalidRenderFrameId();
453 Close(); 618 Close();
454 } 619 }
455 620
456 // TODO(hclam): Add tests for data conversation in low latency mode. 621 // TODO(hclam): Add tests for data conversation in low latency mode.
457 622
458 } // namespace content 623 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698