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.
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 "testing/gtest/include/gtest/gtest.h"
21 const int kRouteId
= 0;
22 const int kAudioSessionId
= 3;
23 const int kVideoSessionId
= 5;
24 const int kRequestId1
= 10;
25 const int kRequestId2
= 20;
26 const int kRequestId3
= 30;
27 const int kRequestId4
= 40;
29 const MediaStreamType kAudioType
= MEDIA_DEVICE_AUDIO_CAPTURE
;
30 const MediaStreamType kVideoType
= MEDIA_DEVICE_VIDEO_CAPTURE
;
32 class MockMediaStreamDispatcherEventHandler
33 : public MediaStreamDispatcherEventHandler
,
34 public base::SupportsWeakPtr
<MockMediaStreamDispatcherEventHandler
> {
36 MockMediaStreamDispatcherEventHandler()
39 virtual void OnStreamGenerated(
41 const std::string
&label
,
42 const StreamDeviceInfoArray
& audio_device_array
,
43 const StreamDeviceInfoArray
& video_device_array
) OVERRIDE
{
44 request_id_
= request_id
;
46 if (audio_device_array
.size()) {
47 DCHECK(audio_device_array
.size() == 1);
48 audio_device_
= audio_device_array
[0];
50 if (video_device_array
.size()) {
51 DCHECK(video_device_array
.size() == 1);
52 video_device_
= video_device_array
[0];
56 virtual void OnStreamGenerationFailed(
58 content::MediaStreamRequestResult result
) OVERRIDE
{
59 request_id_
= request_id
;
62 virtual void OnDeviceStopped(const std::string
& label
,
63 const StreamDeviceInfo
& device_info
) OVERRIDE
{
64 device_stopped_label_
= label
;
65 if (IsVideoMediaType(device_info
.device
.type
)) {
66 EXPECT_TRUE(StreamDeviceInfo::IsEqual(video_device_
, device_info
));
68 if (IsAudioInputMediaType(device_info
.device
.type
)) {
69 EXPECT_TRUE(StreamDeviceInfo::IsEqual(audio_device_
, device_info
));
73 virtual void OnDevicesEnumerated(
75 const StreamDeviceInfoArray
& device_array
) OVERRIDE
{
76 request_id_
= request_id
;
79 virtual void OnDeviceOpened(
81 const std::string
& label
,
82 const StreamDeviceInfo
& video_device
) OVERRIDE
{
83 request_id_
= request_id
;
87 virtual void OnDeviceOpenFailed(int request_id
) OVERRIDE
{
88 request_id_
= request_id
;
91 void ResetStoredParameters() {
94 device_stopped_label_
= "";
95 audio_device_
= StreamDeviceInfo();
96 video_device_
= StreamDeviceInfo();
101 std::string device_stopped_label_
;
102 StreamDeviceInfo audio_device_
;
103 StreamDeviceInfo video_device_
;
106 class MediaStreamDispatcherUnderTest
: public MediaStreamDispatcher
{
108 MediaStreamDispatcherUnderTest() : MediaStreamDispatcher(NULL
) {}
110 using MediaStreamDispatcher::GetNextIpcIdForTest
;
111 using RenderViewObserver::OnMessageReceived
;
114 class MediaStreamDispatcherTest
: public ::testing::Test
{
116 MediaStreamDispatcherTest()
117 : dispatcher_(new MediaStreamDispatcherUnderTest()),
118 handler_(new MockMediaStreamDispatcherEventHandler
),
119 security_origin_("http://test.com"),
123 // Generates a request for a MediaStream and returns the request id that is
124 // used in IPC. Use this returned id in CompleteGenerateStream to identify
126 int GenerateStream(const StreamOptions
& options
, int request_id
) {
127 int next_ipc_id
= dispatcher_
->GetNextIpcIdForTest();
128 dispatcher_
->GenerateStream(request_id
, handler_
.get()->AsWeakPtr(),
129 options
, security_origin_
);
133 // CompleteGenerateStream create a MediaStreamMsg_StreamGenerated instance
134 // and call the MediaStreamDispathcer::OnMessageReceived. |ipc_id| must be the
135 // the id returned by GenerateStream.
136 std::string
CompleteGenerateStream(int ipc_id
, const StreamOptions
& options
,
138 StreamDeviceInfoArray
audio_device_array(options
.audio_requested
? 1 : 0);
139 if (options
.audio_requested
) {
140 StreamDeviceInfo audio_device_info
;
141 audio_device_info
.device
.name
= "Microphone";
142 audio_device_info
.device
.type
= kAudioType
;
143 audio_device_info
.session_id
= kAudioSessionId
;
144 audio_device_array
[0] = audio_device_info
;
147 StreamDeviceInfoArray
video_device_array(options
.video_requested
? 1 : 0);
148 if (options
.video_requested
) {
149 StreamDeviceInfo video_device_info
;
150 video_device_info
.device
.name
= "Camera";
151 video_device_info
.device
.type
= kVideoType
;
152 video_device_info
.session_id
= kVideoSessionId
;
153 video_device_array
[0] = video_device_info
;
156 std::string label
= "stream" + base::IntToString(ipc_id
);
158 handler_
->ResetStoredParameters();
159 dispatcher_
->OnMessageReceived(MediaStreamMsg_StreamGenerated(
160 kRouteId
, ipc_id
, label
,
161 audio_device_array
, video_device_array
));
163 EXPECT_EQ(handler_
->request_id_
, request_id
);
164 EXPECT_EQ(handler_
->label_
, label
);
166 if (options
.audio_requested
)
167 EXPECT_EQ(dispatcher_
->audio_session_id(label
, 0), kAudioSessionId
);
169 if (options
.video_requested
)
170 EXPECT_EQ(dispatcher_
->video_session_id(label
, 0), kVideoSessionId
);
176 base::MessageLoop message_loop_
;
177 scoped_ptr
<MediaStreamDispatcherUnderTest
> dispatcher_
;
178 scoped_ptr
<MockMediaStreamDispatcherEventHandler
> handler_
;
179 GURL security_origin_
;
185 TEST_F(MediaStreamDispatcherTest
, GenerateStreamAndStopDevices
) {
186 StreamOptions
options(true, true);
188 int ipc_request_id1
= GenerateStream(options
, kRequestId1
);
189 int ipc_request_id2
= GenerateStream(options
, kRequestId2
);
190 EXPECT_NE(ipc_request_id1
, ipc_request_id2
);
192 // Complete the creation of stream1.
193 const std::string
& label1
= CompleteGenerateStream(ipc_request_id1
, options
,
196 // Complete the creation of stream2.
197 const std::string
& label2
= CompleteGenerateStream(ipc_request_id2
, options
,
200 // Stop the actual audio device and verify that there is no valid
202 dispatcher_
->StopStreamDevice(handler_
->audio_device_
);
203 EXPECT_EQ(dispatcher_
->audio_session_id(label1
, 0),
204 StreamDeviceInfo::kNoId
);
205 EXPECT_EQ(dispatcher_
->audio_session_id(label2
, 0),
206 StreamDeviceInfo::kNoId
);
208 // Stop the actual video device and verify that there is no valid
210 dispatcher_
->StopStreamDevice(handler_
->video_device_
);
211 EXPECT_EQ(dispatcher_
->video_session_id(label1
, 0),
212 StreamDeviceInfo::kNoId
);
213 EXPECT_EQ(dispatcher_
->video_session_id(label2
, 0),
214 StreamDeviceInfo::kNoId
);
217 TEST_F(MediaStreamDispatcherTest
, BasicVideoDevice
) {
218 scoped_ptr
<MediaStreamDispatcher
> dispatcher(new MediaStreamDispatcher(NULL
));
219 scoped_ptr
<MockMediaStreamDispatcherEventHandler
>
220 handler1(new MockMediaStreamDispatcherEventHandler
);
221 scoped_ptr
<MockMediaStreamDispatcherEventHandler
>
222 handler2(new MockMediaStreamDispatcherEventHandler
);
223 GURL security_origin
;
225 int ipc_request_id1
= dispatcher
->next_ipc_id_
;
226 dispatcher
->EnumerateDevices(
227 kRequestId1
, handler1
.get()->AsWeakPtr(),
230 int ipc_request_id2
= dispatcher
->next_ipc_id_
;
231 EXPECT_NE(ipc_request_id1
, ipc_request_id2
);
232 dispatcher
->EnumerateDevices(
233 kRequestId2
, handler2
.get()->AsWeakPtr(),
236 EXPECT_EQ(dispatcher
->requests_
.size(), size_t(2));
238 StreamDeviceInfoArray
video_device_array(1);
239 StreamDeviceInfo video_device_info
;
240 video_device_info
.device
.name
= "Camera";
241 video_device_info
.device
.id
= "device_path";
242 video_device_info
.device
.type
= kVideoType
;
243 video_device_info
.session_id
= kVideoSessionId
;
244 video_device_array
[0] = video_device_info
;
246 // Complete the first enumeration request.
247 dispatcher
->OnMessageReceived(MediaStreamMsg_DevicesEnumerated(
248 kRouteId
, ipc_request_id1
, video_device_array
));
249 EXPECT_EQ(handler1
->request_id_
, kRequestId1
);
251 dispatcher
->OnMessageReceived(MediaStreamMsg_DevicesEnumerated(
252 kRouteId
, ipc_request_id2
, video_device_array
));
253 EXPECT_EQ(handler2
->request_id_
, kRequestId2
);
255 EXPECT_EQ(dispatcher
->requests_
.size(), size_t(2));
256 EXPECT_EQ(dispatcher
->label_stream_map_
.size(), size_t(0));
258 int ipc_request_id3
= dispatcher
->next_ipc_id_
;
259 dispatcher
->OpenDevice(kRequestId3
, handler1
.get()->AsWeakPtr(),
260 video_device_info
.device
.id
,
263 int ipc_request_id4
= dispatcher
->next_ipc_id_
;
264 EXPECT_NE(ipc_request_id3
, ipc_request_id4
);
265 dispatcher
->OpenDevice(kRequestId4
, handler1
.get()->AsWeakPtr(),
266 video_device_info
.device
.id
,
269 EXPECT_EQ(dispatcher
->requests_
.size(), size_t(4));
271 // Complete the OpenDevice of request 1.
272 std::string stream_label1
= std::string("stream1");
273 dispatcher
->OnMessageReceived(MediaStreamMsg_DeviceOpened(
274 kRouteId
, ipc_request_id3
, stream_label1
, video_device_info
));
275 EXPECT_EQ(handler1
->request_id_
, kRequestId3
);
277 // Complete the OpenDevice of request 2.
278 std::string stream_label2
= std::string("stream2");
279 dispatcher
->OnMessageReceived(MediaStreamMsg_DeviceOpened(
280 kRouteId
, ipc_request_id4
, stream_label2
, video_device_info
));
281 EXPECT_EQ(handler1
->request_id_
, kRequestId4
);
283 EXPECT_EQ(dispatcher
->requests_
.size(), size_t(2));
284 EXPECT_EQ(dispatcher
->label_stream_map_
.size(), size_t(2));
286 // Check the video_session_id.
287 EXPECT_EQ(dispatcher
->video_session_id(stream_label1
, 0), kVideoSessionId
);
288 EXPECT_EQ(dispatcher
->video_session_id(stream_label2
, 0), kVideoSessionId
);
290 // Close the device from request 2.
291 dispatcher
->CloseDevice(stream_label2
);
292 EXPECT_EQ(dispatcher
->video_session_id(stream_label2
, 0),
293 StreamDeviceInfo::kNoId
);
295 // Close the device from request 1.
296 dispatcher
->CloseDevice(stream_label1
);
297 EXPECT_EQ(dispatcher
->video_session_id(stream_label1
, 0),
298 StreamDeviceInfo::kNoId
);
299 EXPECT_EQ(dispatcher
->label_stream_map_
.size(), size_t(0));
301 // Verify that the request have been completed.
302 EXPECT_EQ(dispatcher
->label_stream_map_
.size(), size_t(0));
303 EXPECT_EQ(dispatcher
->requests_
.size(), size_t(2));
306 TEST_F(MediaStreamDispatcherTest
, TestFailure
) {
307 scoped_ptr
<MediaStreamDispatcher
> dispatcher(new MediaStreamDispatcher(NULL
));
308 scoped_ptr
<MockMediaStreamDispatcherEventHandler
>
309 handler(new MockMediaStreamDispatcherEventHandler
);
310 StreamOptions
components(true, true);
311 GURL security_origin
;
313 // Test failure when creating a stream.
314 int ipc_request_id1
= dispatcher
->next_ipc_id_
;
315 dispatcher
->GenerateStream(kRequestId1
, handler
.get()->AsWeakPtr(),
316 components
, security_origin
);
317 dispatcher
->OnMessageReceived(MediaStreamMsg_StreamGenerationFailed(
318 kRouteId
, ipc_request_id1
, MEDIA_DEVICE_PERMISSION_DENIED
));
320 // Verify that the request have been completed.
321 EXPECT_EQ(handler
->request_id_
, kRequestId1
);
322 EXPECT_EQ(dispatcher
->requests_
.size(), size_t(0));
324 // Create a new stream.
325 ipc_request_id1
= dispatcher
->next_ipc_id_
;
326 dispatcher
->GenerateStream(kRequestId1
, handler
.get()->AsWeakPtr(),
327 components
, security_origin
);
329 StreamDeviceInfoArray
audio_device_array(1);
330 StreamDeviceInfo audio_device_info
;
331 audio_device_info
.device
.name
= "Microphone";
332 audio_device_info
.device
.type
= kAudioType
;
333 audio_device_info
.session_id
= kAudioSessionId
;
334 audio_device_array
[0] = audio_device_info
;
336 StreamDeviceInfoArray
video_device_array(1);
337 StreamDeviceInfo video_device_info
;
338 video_device_info
.device
.name
= "Camera";
339 video_device_info
.device
.type
= kVideoType
;
340 video_device_info
.session_id
= kVideoSessionId
;
341 video_device_array
[0] = video_device_info
;
343 // Complete the creation of stream1.
344 std::string stream_label1
= std::string("stream1");
345 dispatcher
->OnMessageReceived(MediaStreamMsg_StreamGenerated(
346 kRouteId
, ipc_request_id1
, stream_label1
,
347 audio_device_array
, video_device_array
));
348 EXPECT_EQ(handler
->request_id_
, kRequestId1
);
349 EXPECT_EQ(handler
->label_
, stream_label1
);
350 EXPECT_EQ(dispatcher
->video_session_id(stream_label1
, 0), kVideoSessionId
);
353 TEST_F(MediaStreamDispatcherTest
, CancelGenerateStream
) {
354 scoped_ptr
<MediaStreamDispatcher
> dispatcher(new MediaStreamDispatcher(NULL
));
355 scoped_ptr
<MockMediaStreamDispatcherEventHandler
>
356 handler(new MockMediaStreamDispatcherEventHandler
);
357 StreamOptions
components(true, true);
358 int ipc_request_id1
= dispatcher
->next_ipc_id_
;
360 dispatcher
->GenerateStream(kRequestId1
, handler
.get()->AsWeakPtr(),
362 dispatcher
->GenerateStream(kRequestId2
, handler
.get()->AsWeakPtr(),
365 EXPECT_EQ(2u, dispatcher
->requests_
.size());
366 dispatcher
->CancelGenerateStream(kRequestId2
, handler
.get()->AsWeakPtr());
367 EXPECT_EQ(1u, dispatcher
->requests_
.size());
369 // Complete the creation of stream1.
370 StreamDeviceInfo audio_device_info
;
371 audio_device_info
.device
.name
= "Microphone";
372 audio_device_info
.device
.type
= kAudioType
;
373 audio_device_info
.session_id
= kAudioSessionId
;
374 StreamDeviceInfoArray
audio_device_array(1);
375 audio_device_array
[0] = audio_device_info
;
377 StreamDeviceInfo video_device_info
;
378 video_device_info
.device
.name
= "Camera";
379 video_device_info
.device
.type
= kVideoType
;
380 video_device_info
.session_id
= kVideoSessionId
;
381 StreamDeviceInfoArray
video_device_array(1);
382 video_device_array
[0] = video_device_info
;
384 std::string stream_label1
= "stream1";
385 dispatcher
->OnMessageReceived(MediaStreamMsg_StreamGenerated(
386 kRouteId
, ipc_request_id1
, stream_label1
,
387 audio_device_array
, video_device_array
));
388 EXPECT_EQ(handler
->request_id_
, kRequestId1
);
389 EXPECT_EQ(handler
->label_
, stream_label1
);
390 EXPECT_EQ(0u, dispatcher
->requests_
.size());
393 // Test that the MediaStreamDispatcherEventHandler is notified when the message
394 // MediaStreamMsg_DeviceStopped is received.
395 TEST_F(MediaStreamDispatcherTest
, DeviceClosed
) {
396 StreamOptions
options(true, true);
398 int ipc_request_id
= GenerateStream(options
, kRequestId1
);
399 const std::string
& label
= CompleteGenerateStream(ipc_request_id
, options
,
402 dispatcher_
->OnMessageReceived(
403 MediaStreamMsg_DeviceStopped(kRouteId
, label
, handler_
->video_device_
));
404 // Verify that MediaStreamDispatcherEventHandler::OnDeviceStopped has been
406 EXPECT_EQ(label
, handler_
->device_stopped_label_
);
407 EXPECT_EQ(dispatcher_
->video_session_id(label
, 0),
408 StreamDeviceInfo::kNoId
);
411 } // namespace content