Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / renderer / media / media_stream_dispatcher_unittest.cc
blob32acc8825446f4ceecbf5d4b7d29cd162da43a0b
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
3 // found in the LICENSE file.
5 #include <string>
7 #include "base/memory/ref_counted.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "content/common/media/media_stream_messages.h"
12 #include "content/public/common/media_stream_request.h"
13 #include "content/renderer/media/media_stream_dispatcher.h"
14 #include "content/renderer/media/media_stream_dispatcher_eventhandler.h"
15 #include "media/audio/audio_parameters.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "url/gurl.h"
19 namespace content {
20 namespace {
22 const int kRouteId = 0;
23 const int kAudioSessionId = 3;
24 const int kVideoSessionId = 5;
25 const int kRequestId1 = 10;
26 const int kRequestId2 = 20;
27 const int kRequestId3 = 30;
28 const int kRequestId4 = 40;
30 const MediaStreamType kAudioType = MEDIA_DEVICE_AUDIO_CAPTURE;
31 const MediaStreamType kVideoType = MEDIA_DEVICE_VIDEO_CAPTURE;
33 class MockMediaStreamDispatcherEventHandler
34 : public MediaStreamDispatcherEventHandler,
35 public base::SupportsWeakPtr<MockMediaStreamDispatcherEventHandler> {
36 public:
37 MockMediaStreamDispatcherEventHandler()
38 : request_id_(-1) {}
40 void OnStreamGenerated(
41 int request_id,
42 const std::string& label,
43 const StreamDeviceInfoArray& audio_device_array,
44 const StreamDeviceInfoArray& video_device_array) override {
45 request_id_ = request_id;
46 label_ = label;
47 if (audio_device_array.size()) {
48 DCHECK(audio_device_array.size() == 1);
49 audio_device_ = audio_device_array[0];
51 if (video_device_array.size()) {
52 DCHECK(video_device_array.size() == 1);
53 video_device_ = video_device_array[0];
57 void OnStreamGenerationFailed(
58 int request_id,
59 content::MediaStreamRequestResult result) override {
60 request_id_ = request_id;
63 void OnDeviceStopped(const std::string& label,
64 const StreamDeviceInfo& device_info) override {
65 device_stopped_label_ = label;
66 if (IsVideoMediaType(device_info.device.type)) {
67 EXPECT_TRUE(StreamDeviceInfo::IsEqual(video_device_, device_info));
69 if (IsAudioInputMediaType(device_info.device.type)) {
70 EXPECT_TRUE(StreamDeviceInfo::IsEqual(audio_device_, device_info));
74 void OnDevicesEnumerated(int request_id,
75 const StreamDeviceInfoArray& device_array) override {
76 request_id_ = request_id;
79 void OnDeviceOpened(int request_id,
80 const std::string& label,
81 const StreamDeviceInfo& video_device) override {
82 request_id_ = request_id;
83 label_ = label;
86 void OnDeviceOpenFailed(int request_id) override { request_id_ = request_id; }
88 void ResetStoredParameters() {
89 request_id_ = -1;
90 label_ = "";
91 device_stopped_label_ = "";
92 audio_device_ = StreamDeviceInfo();
93 video_device_ = StreamDeviceInfo();
96 int request_id_;
97 std::string label_;
98 std::string device_stopped_label_;
99 StreamDeviceInfo audio_device_;
100 StreamDeviceInfo video_device_;
103 class MediaStreamDispatcherUnderTest : public MediaStreamDispatcher {
104 public:
105 MediaStreamDispatcherUnderTest() : MediaStreamDispatcher(NULL) {}
107 using MediaStreamDispatcher::GetNextIpcIdForTest;
108 using RenderFrameObserver::OnMessageReceived;
111 class MediaStreamDispatcherTest : public ::testing::Test {
112 public:
113 MediaStreamDispatcherTest()
114 : dispatcher_(new MediaStreamDispatcherUnderTest()),
115 handler_(new MockMediaStreamDispatcherEventHandler),
116 security_origin_("http://test.com"),
117 request_id_(10) {
120 // Generates a request for a MediaStream and returns the request id that is
121 // used in IPC. Use this returned id in CompleteGenerateStream to identify
122 // the request.
123 int GenerateStream(const StreamOptions& options, int request_id) {
124 int next_ipc_id = dispatcher_->GetNextIpcIdForTest();
125 dispatcher_->GenerateStream(request_id, handler_.get()->AsWeakPtr(),
126 options, security_origin_);
127 return next_ipc_id;
130 // CompleteGenerateStream create a MediaStreamMsg_StreamGenerated instance
131 // and call the MediaStreamDispathcer::OnMessageReceived. |ipc_id| must be the
132 // the id returned by GenerateStream.
133 std::string CompleteGenerateStream(int ipc_id, const StreamOptions& options,
134 int request_id) {
135 StreamDeviceInfoArray audio_device_array(options.audio_requested ? 1 : 0);
136 if (options.audio_requested) {
137 StreamDeviceInfo audio_device_info;
138 audio_device_info.device.name = "Microphone";
139 audio_device_info.device.type = kAudioType;
140 audio_device_info.session_id = kAudioSessionId;
141 audio_device_array[0] = audio_device_info;
144 StreamDeviceInfoArray video_device_array(options.video_requested ? 1 : 0);
145 if (options.video_requested) {
146 StreamDeviceInfo video_device_info;
147 video_device_info.device.name = "Camera";
148 video_device_info.device.type = kVideoType;
149 video_device_info.session_id = kVideoSessionId;
150 video_device_array[0] = video_device_info;
153 std::string label = "stream" + base::IntToString(ipc_id);
155 handler_->ResetStoredParameters();
156 dispatcher_->OnMessageReceived(MediaStreamMsg_StreamGenerated(
157 kRouteId, ipc_id, label,
158 audio_device_array, video_device_array));
160 EXPECT_EQ(handler_->request_id_, request_id);
161 EXPECT_EQ(handler_->label_, label);
163 if (options.audio_requested)
164 EXPECT_EQ(dispatcher_->audio_session_id(label, 0), kAudioSessionId);
166 if (options.video_requested)
167 EXPECT_EQ(dispatcher_->video_session_id(label, 0), kVideoSessionId);
169 return label;
172 protected:
173 base::MessageLoop message_loop_;
174 scoped_ptr<MediaStreamDispatcherUnderTest> dispatcher_;
175 scoped_ptr<MockMediaStreamDispatcherEventHandler> handler_;
176 GURL security_origin_;
177 int request_id_;
180 } // namespace
182 TEST_F(MediaStreamDispatcherTest, GenerateStreamAndStopDevices) {
183 StreamOptions options(true, true);
185 int ipc_request_id1 = GenerateStream(options, kRequestId1);
186 int ipc_request_id2 = GenerateStream(options, kRequestId2);
187 EXPECT_NE(ipc_request_id1, ipc_request_id2);
189 // Complete the creation of stream1.
190 const std::string& label1 = CompleteGenerateStream(ipc_request_id1, options,
191 kRequestId1);
193 // Complete the creation of stream2.
194 const std::string& label2 = CompleteGenerateStream(ipc_request_id2, options,
195 kRequestId2);
197 // Stop the actual audio device and verify that there is no valid
198 // |session_id|.
199 dispatcher_->StopStreamDevice(handler_->audio_device_);
200 EXPECT_EQ(dispatcher_->audio_session_id(label1, 0),
201 StreamDeviceInfo::kNoId);
202 EXPECT_EQ(dispatcher_->audio_session_id(label2, 0),
203 StreamDeviceInfo::kNoId);
205 // Stop the actual video device and verify that there is no valid
206 // |session_id|.
207 dispatcher_->StopStreamDevice(handler_->video_device_);
208 EXPECT_EQ(dispatcher_->video_session_id(label1, 0),
209 StreamDeviceInfo::kNoId);
210 EXPECT_EQ(dispatcher_->video_session_id(label2, 0),
211 StreamDeviceInfo::kNoId);
214 TEST_F(MediaStreamDispatcherTest, BasicVideoDevice) {
215 scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
216 scoped_ptr<MockMediaStreamDispatcherEventHandler>
217 handler1(new MockMediaStreamDispatcherEventHandler);
218 scoped_ptr<MockMediaStreamDispatcherEventHandler>
219 handler2(new MockMediaStreamDispatcherEventHandler);
220 GURL security_origin;
222 int ipc_request_id1 = dispatcher->next_ipc_id_;
223 dispatcher->EnumerateDevices(
224 kRequestId1, handler1.get()->AsWeakPtr(),
225 kVideoType,
226 security_origin);
227 int ipc_request_id2 = dispatcher->next_ipc_id_;
228 EXPECT_NE(ipc_request_id1, ipc_request_id2);
229 dispatcher->EnumerateDevices(
230 kRequestId2, handler2.get()->AsWeakPtr(),
231 kVideoType,
232 security_origin);
233 EXPECT_EQ(dispatcher->requests_.size(), size_t(2));
235 StreamDeviceInfoArray video_device_array(1);
236 StreamDeviceInfo video_device_info;
237 video_device_info.device.name = "Camera";
238 video_device_info.device.id = "device_path";
239 video_device_info.device.type = kVideoType;
240 video_device_info.session_id = kVideoSessionId;
241 video_device_array[0] = video_device_info;
243 // Complete the first enumeration request.
244 dispatcher->OnMessageReceived(MediaStreamMsg_DevicesEnumerated(
245 kRouteId, ipc_request_id1, video_device_array));
246 EXPECT_EQ(handler1->request_id_, kRequestId1);
248 dispatcher->OnMessageReceived(MediaStreamMsg_DevicesEnumerated(
249 kRouteId, ipc_request_id2, video_device_array));
250 EXPECT_EQ(handler2->request_id_, kRequestId2);
252 EXPECT_EQ(dispatcher->requests_.size(), size_t(2));
253 EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0));
255 int ipc_request_id3 = dispatcher->next_ipc_id_;
256 dispatcher->OpenDevice(kRequestId3, handler1.get()->AsWeakPtr(),
257 video_device_info.device.id,
258 kVideoType,
259 security_origin);
260 int ipc_request_id4 = dispatcher->next_ipc_id_;
261 EXPECT_NE(ipc_request_id3, ipc_request_id4);
262 dispatcher->OpenDevice(kRequestId4, handler1.get()->AsWeakPtr(),
263 video_device_info.device.id,
264 kVideoType,
265 security_origin);
266 EXPECT_EQ(dispatcher->requests_.size(), size_t(4));
268 // Complete the OpenDevice of request 1.
269 std::string stream_label1 = std::string("stream1");
270 dispatcher->OnMessageReceived(MediaStreamMsg_DeviceOpened(
271 kRouteId, ipc_request_id3, stream_label1, video_device_info));
272 EXPECT_EQ(handler1->request_id_, kRequestId3);
274 // Complete the OpenDevice of request 2.
275 std::string stream_label2 = std::string("stream2");
276 dispatcher->OnMessageReceived(MediaStreamMsg_DeviceOpened(
277 kRouteId, ipc_request_id4, stream_label2, video_device_info));
278 EXPECT_EQ(handler1->request_id_, kRequestId4);
280 EXPECT_EQ(dispatcher->requests_.size(), size_t(2));
281 EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(2));
283 // Check the video_session_id.
284 EXPECT_EQ(dispatcher->video_session_id(stream_label1, 0), kVideoSessionId);
285 EXPECT_EQ(dispatcher->video_session_id(stream_label2, 0), kVideoSessionId);
287 // Close the device from request 2.
288 dispatcher->CloseDevice(stream_label2);
289 EXPECT_EQ(dispatcher->video_session_id(stream_label2, 0),
290 StreamDeviceInfo::kNoId);
292 // Close the device from request 1.
293 dispatcher->CloseDevice(stream_label1);
294 EXPECT_EQ(dispatcher->video_session_id(stream_label1, 0),
295 StreamDeviceInfo::kNoId);
296 EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0));
298 // Verify that the request have been completed.
299 EXPECT_EQ(dispatcher->label_stream_map_.size(), size_t(0));
300 EXPECT_EQ(dispatcher->requests_.size(), size_t(2));
303 TEST_F(MediaStreamDispatcherTest, TestFailure) {
304 scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
305 scoped_ptr<MockMediaStreamDispatcherEventHandler>
306 handler(new MockMediaStreamDispatcherEventHandler);
307 StreamOptions components(true, true);
308 GURL security_origin;
310 // Test failure when creating a stream.
311 int ipc_request_id1 = dispatcher->next_ipc_id_;
312 dispatcher->GenerateStream(kRequestId1, handler.get()->AsWeakPtr(),
313 components, security_origin);
314 dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerationFailed(
315 kRouteId, ipc_request_id1, MEDIA_DEVICE_PERMISSION_DENIED));
317 // Verify that the request have been completed.
318 EXPECT_EQ(handler->request_id_, kRequestId1);
319 EXPECT_EQ(dispatcher->requests_.size(), size_t(0));
321 // Create a new stream.
322 ipc_request_id1 = dispatcher->next_ipc_id_;
323 dispatcher->GenerateStream(kRequestId1, handler.get()->AsWeakPtr(),
324 components, security_origin);
326 StreamDeviceInfoArray audio_device_array(1);
327 StreamDeviceInfo audio_device_info;
328 audio_device_info.device.name = "Microphone";
329 audio_device_info.device.type = kAudioType;
330 audio_device_info.session_id = kAudioSessionId;
331 audio_device_array[0] = audio_device_info;
333 StreamDeviceInfoArray video_device_array(1);
334 StreamDeviceInfo video_device_info;
335 video_device_info.device.name = "Camera";
336 video_device_info.device.type = kVideoType;
337 video_device_info.session_id = kVideoSessionId;
338 video_device_array[0] = video_device_info;
340 // Complete the creation of stream1.
341 std::string stream_label1 = std::string("stream1");
342 dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated(
343 kRouteId, ipc_request_id1, stream_label1,
344 audio_device_array, video_device_array));
345 EXPECT_EQ(handler->request_id_, kRequestId1);
346 EXPECT_EQ(handler->label_, stream_label1);
347 EXPECT_EQ(dispatcher->video_session_id(stream_label1, 0), kVideoSessionId);
350 TEST_F(MediaStreamDispatcherTest, CancelGenerateStream) {
351 scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
352 scoped_ptr<MockMediaStreamDispatcherEventHandler>
353 handler(new MockMediaStreamDispatcherEventHandler);
354 StreamOptions components(true, true);
355 int ipc_request_id1 = dispatcher->next_ipc_id_;
357 dispatcher->GenerateStream(kRequestId1, handler.get()->AsWeakPtr(),
358 components, GURL());
359 dispatcher->GenerateStream(kRequestId2, handler.get()->AsWeakPtr(),
360 components, GURL());
362 EXPECT_EQ(2u, dispatcher->requests_.size());
363 dispatcher->CancelGenerateStream(kRequestId2, handler.get()->AsWeakPtr());
364 EXPECT_EQ(1u, dispatcher->requests_.size());
366 // Complete the creation of stream1.
367 StreamDeviceInfo audio_device_info;
368 audio_device_info.device.name = "Microphone";
369 audio_device_info.device.type = kAudioType;
370 audio_device_info.session_id = kAudioSessionId;
371 StreamDeviceInfoArray audio_device_array(1);
372 audio_device_array[0] = audio_device_info;
374 StreamDeviceInfo video_device_info;
375 video_device_info.device.name = "Camera";
376 video_device_info.device.type = kVideoType;
377 video_device_info.session_id = kVideoSessionId;
378 StreamDeviceInfoArray video_device_array(1);
379 video_device_array[0] = video_device_info;
381 std::string stream_label1 = "stream1";
382 dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated(
383 kRouteId, ipc_request_id1, stream_label1,
384 audio_device_array, video_device_array));
385 EXPECT_EQ(handler->request_id_, kRequestId1);
386 EXPECT_EQ(handler->label_, stream_label1);
387 EXPECT_EQ(0u, dispatcher->requests_.size());
390 // Test that the MediaStreamDispatcherEventHandler is notified when the message
391 // MediaStreamMsg_DeviceStopped is received.
392 TEST_F(MediaStreamDispatcherTest, DeviceClosed) {
393 StreamOptions options(true, true);
395 int ipc_request_id = GenerateStream(options, kRequestId1);
396 const std::string& label = CompleteGenerateStream(ipc_request_id, options,
397 kRequestId1);
399 dispatcher_->OnMessageReceived(
400 MediaStreamMsg_DeviceStopped(kRouteId, label, handler_->video_device_));
401 // Verify that MediaStreamDispatcherEventHandler::OnDeviceStopped has been
402 // called.
403 EXPECT_EQ(label, handler_->device_stopped_label_);
404 EXPECT_EQ(dispatcher_->video_session_id(label, 0),
405 StreamDeviceInfo::kNoId);
408 TEST_F(MediaStreamDispatcherTest, CheckDuckingState) {
409 scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
410 scoped_ptr<MockMediaStreamDispatcherEventHandler>
411 handler(new MockMediaStreamDispatcherEventHandler);
412 StreamOptions components(true, false); // audio only.
413 int ipc_request_id1 = dispatcher->next_ipc_id_;
415 dispatcher->GenerateStream(kRequestId1, handler.get()->AsWeakPtr(),
416 components, GURL());
417 EXPECT_EQ(1u, dispatcher->requests_.size());
419 // Ducking isn't active at this point.
420 EXPECT_FALSE(dispatcher->IsAudioDuckingActive());
422 // Complete the creation of stream1 with a single audio track that has
423 // ducking enabled.
424 StreamDeviceInfoArray audio_device_array(1);
425 StreamDeviceInfo& audio_device_info = audio_device_array[0];
426 audio_device_info.device.name = "Microphone";
427 audio_device_info.device.type = kAudioType;
428 audio_device_info.session_id = kAudioSessionId;
429 audio_device_info.device.input.effects = media::AudioParameters::DUCKING;
431 StreamDeviceInfoArray video_device_array; // Empty for this test.
433 const char kStreamLabel[] = "stream1";
434 dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated(
435 kRouteId, ipc_request_id1, kStreamLabel,
436 audio_device_array, video_device_array));
437 EXPECT_EQ(handler->request_id_, kRequestId1);
438 EXPECT_EQ(0u, dispatcher->requests_.size());
440 // Ducking should now be reported as active.
441 EXPECT_TRUE(dispatcher->IsAudioDuckingActive());
443 // Stop the device (removes the stream).
444 dispatcher->OnMessageReceived(
445 MediaStreamMsg_DeviceStopped(kRouteId, kStreamLabel,
446 handler->audio_device_));
448 // Ducking should now be reported as inactive again.
449 EXPECT_FALSE(dispatcher->IsAudioDuckingActive());
451 // Now do the same sort of test with the DUCKING flag off.
452 audio_device_info.device.input.effects =
453 media::AudioParameters::ECHO_CANCELLER;
455 dispatcher->OnMessageReceived(MediaStreamMsg_StreamGenerated(
456 kRouteId, ipc_request_id1, kStreamLabel,
457 audio_device_array, video_device_array));
458 EXPECT_EQ(handler->request_id_, kRequestId1);
459 EXPECT_EQ(0u, dispatcher->requests_.size());
461 // Ducking should still be reported as not active.
462 EXPECT_FALSE(dispatcher->IsAudioDuckingActive());
464 // Stop the device (removes the stream).
465 dispatcher->OnMessageReceived(
466 MediaStreamMsg_DeviceStopped(kRouteId, kStreamLabel,
467 handler->audio_device_));
470 } // namespace content