- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / media / media_stream_dispatcher_host_unittest.cc
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.
4
5 #include <string>
6 #include <queue>
7
8 #include "base/bind.h"
9 #include "base/callback_helpers.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/run_loop.h"
12 #include "content/browser/browser_thread_impl.h"
13 #include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
14 #include "content/browser/renderer_host/media/media_stream_manager.h"
15 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
16 #include "content/common/media/media_stream_messages.h"
17 #include "content/common/media/media_stream_options.h"
18 #include "content/public/test/mock_resource_context.h"
19 #include "content/public/test/test_browser_thread_bundle.h"
20 #include "content/test/test_content_browser_client.h"
21 #include "content/test/test_content_client.h"
22 #include "ipc/ipc_message_macros.h"
23 #include "media/audio/audio_manager.h"
24 #include "media/video/capture/fake_video_capture_device.h"
25 #include "net/url_request/url_request_context.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28
29 using ::testing::_;
30 using ::testing::DeleteArg;
31 using ::testing::DoAll;
32 using ::testing::Return;
33 using ::testing::SaveArg;
34
35 const int kProcessId = 5;
36 const int kRenderId = 6;
37 const int kPageRequestId = 7;
38
39 namespace content {
40
41 class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
42                                       public TestContentBrowserClient {
43  public:
44   MockMediaStreamDispatcherHost(
45       const scoped_refptr<base::MessageLoopProxy>& message_loop,
46       MediaStreamManager* manager)
47       : MediaStreamDispatcherHost(kProcessId, manager),
48         message_loop_(message_loop) {}
49
50   // A list of mock methods.
51   MOCK_METHOD4(OnStreamGenerated,
52                void(int routing_id, int request_id, int audio_array_size,
53                     int video_array_size));
54   MOCK_METHOD2(OnStreamGenerationFailed, void(int routing_id, int request_id));
55   MOCK_METHOD1(OnStopGeneratedStreamFromBrowser,
56                void(int routing_id));
57   MOCK_METHOD2(OnDeviceOpened,
58                void(int routing_id, int request_id));
59
60   // Accessor to private functions.
61   void OnGenerateStream(int render_view_id,
62                         int page_request_id,
63                         const StreamOptions& components,
64                         const base::Closure& quit_closure) {
65     quit_closures_.push(quit_closure);
66     MediaStreamDispatcherHost::OnGenerateStream(
67         render_view_id, page_request_id, components, GURL());
68   }
69
70   void OnStopStreamDevice(int render_view_id,
71                           const std::string& device_id) {
72     MediaStreamDispatcherHost::OnStopStreamDevice(render_view_id, device_id);
73   }
74
75   void OnOpenDevice(int render_view_id,
76                     int page_request_id,
77                     const std::string& device_id,
78                     MediaStreamType type,
79                     const base::Closure& quit_closure) {
80     quit_closures_.push(quit_closure);
81     MediaStreamDispatcherHost::OnOpenDevice(
82         render_view_id, page_request_id, device_id, type, GURL());
83   }
84
85   bool FindExistingRequestedDeviceInfo(const std::string& device_id,
86                                        MediaStreamRequestType request_type,
87                                        StreamDeviceInfo* device_info) {
88     MediaRequestState request_state;
89     return media_stream_manager_->FindExistingRequestedDeviceInfo(
90         kProcessId, kRenderId, request_type, device_id, device_info,
91         &request_state);
92   }
93
94   std::string label_;
95   StreamDeviceInfoArray audio_devices_;
96   StreamDeviceInfoArray video_devices_;
97   StreamDeviceInfo opened_device_;
98
99  private:
100   virtual ~MockMediaStreamDispatcherHost() {}
101
102   // This method is used to dispatch IPC messages to the renderer. We intercept
103   // these messages here and dispatch to our mock methods to verify the
104   // conversation between this object and the renderer.
105   virtual bool Send(IPC::Message* message) OVERRIDE {
106     CHECK(message);
107
108     // In this method we dispatch the messages to the according handlers as if
109     // we are the renderer.
110     bool handled = true;
111     IPC_BEGIN_MESSAGE_MAP(MockMediaStreamDispatcherHost, *message)
112       IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerated, OnStreamGenerated)
113       IPC_MESSAGE_HANDLER(MediaStreamMsg_StreamGenerationFailed,
114                           OnStreamGenerationFailed)
115       IPC_MESSAGE_HANDLER(MediaStreamMsg_StopGeneratedStream,
116                           OnStopGeneratedStreamFromBrowser)
117       IPC_MESSAGE_HANDLER(MediaStreamMsg_DeviceOpened, OnDeviceOpened)
118       IPC_MESSAGE_UNHANDLED(handled = false)
119     IPC_END_MESSAGE_MAP()
120     EXPECT_TRUE(handled);
121
122     delete message;
123     return true;
124   }
125
126   // These handler methods do minimal things and delegate to the mock methods.
127   void OnStreamGenerated(
128       const IPC::Message& msg,
129       int request_id,
130       std::string label,
131       StreamDeviceInfoArray audio_device_list,
132       StreamDeviceInfoArray video_device_list) {
133     OnStreamGenerated(msg.routing_id(), request_id, audio_device_list.size(),
134         video_device_list.size());
135     // Notify that the event have occurred.
136     base::Closure quit_closure = quit_closures_.front();
137     quit_closures_.pop();
138     message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure));
139
140     label_ = label;
141     audio_devices_ = audio_device_list;
142     video_devices_ = video_device_list;
143   }
144
145   void OnStreamGenerationFailed(const IPC::Message& msg, int request_id) {
146     OnStreamGenerationFailed(msg.routing_id(), request_id);
147     if (!quit_closures_.empty()) {
148       base::Closure quit_closure = quit_closures_.front();
149       quit_closures_.pop();
150       message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure));
151     }
152
153     label_= "";
154   }
155
156   void OnStopGeneratedStreamFromBrowser(const IPC::Message& msg,
157                                         const std::string& label) {
158     OnStopGeneratedStreamFromBrowser(msg.routing_id());
159     // Notify that the event have occurred.
160     if (!quit_closures_.empty()) {
161       base::Closure quit_closure = quit_closures_.front();
162       quit_closures_.pop();
163       message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure));
164     }
165     label_ = "";
166   }
167
168   void OnDeviceOpened(const IPC::Message& msg,
169                       int request_id,
170                       const std::string& label,
171                       const StreamDeviceInfo& device) {
172     base::Closure quit_closure = quit_closures_.front();
173     quit_closures_.pop();
174     message_loop_->PostTask(FROM_HERE, base::ResetAndReturn(&quit_closure));
175     label_ = label;
176     opened_device_ = device;
177   }
178
179   scoped_refptr<base::MessageLoopProxy> message_loop_;
180
181   std::queue<base::Closure> quit_closures_;
182 };
183
184 class MockMediaStreamUIProxy : public FakeMediaStreamUIProxy {
185  public:
186   MOCK_METHOD1(OnStarted, void(const base::Closure& stop));
187 };
188
189 class MediaStreamDispatcherHostTest : public testing::Test {
190  public:
191   MediaStreamDispatcherHostTest()
192       : old_browser_client_(NULL),
193         thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {
194     // Create our own MediaStreamManager.
195     audio_manager_.reset(media::AudioManager::Create());
196     media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
197     // Make sure we use fake devices to avoid long delays.
198     media_stream_manager_->UseFakeDevice();
199
200     host_ = new MockMediaStreamDispatcherHost(base::MessageLoopProxy::current(),
201                                               media_stream_manager_.get());
202
203     // Use the fake content client and browser.
204     content_client_.reset(new TestContentClient());
205     SetContentClient(content_client_.get());
206     old_browser_client_ = SetBrowserClientForTesting(host_.get());
207   }
208
209   virtual ~MediaStreamDispatcherHostTest() {
210     // Recover the old browser client and content client.
211     SetBrowserClientForTesting(old_browser_client_);
212     content_client_.reset();
213     media_stream_manager_->WillDestroyCurrentMessageLoop();
214   }
215
216   virtual void TearDown() OVERRIDE {
217     host_->OnChannelClosing();
218   }
219
220  protected:
221   virtual void SetupFakeUI(bool expect_started) {
222     scoped_ptr<MockMediaStreamUIProxy> stream_ui(new MockMediaStreamUIProxy());
223     if (expect_started) {
224       EXPECT_CALL(*stream_ui, OnStarted(_));
225     }
226     media_stream_manager_->UseFakeUI(
227         stream_ui.PassAs<FakeMediaStreamUIProxy>());
228   }
229
230   void GenerateStreamAndWaitForResult(int render_view_id,
231                                       int page_request_id,
232                                       const StreamOptions& options) {
233     base::RunLoop run_loop;
234     host_->OnGenerateStream(render_view_id, page_request_id, options,
235                             run_loop.QuitClosure());
236     run_loop.Run();
237   }
238
239   void OpenVideoDeviceAndWaitForResult(int render_view_id,
240                                        int page_request_id,
241                                        const std::string& device_id) {
242     base::RunLoop run_loop;
243     host_->OnOpenDevice(render_view_id, page_request_id, device_id,
244                         MEDIA_DEVICE_VIDEO_CAPTURE,
245                         run_loop.QuitClosure());
246     run_loop.Run();
247   }
248
249   scoped_refptr<MockMediaStreamDispatcherHost> host_;
250   scoped_ptr<media::AudioManager> audio_manager_;
251   scoped_ptr<MediaStreamManager> media_stream_manager_;
252   ContentBrowserClient* old_browser_client_;
253   scoped_ptr<ContentClient> content_client_;
254   content::TestBrowserThreadBundle thread_bundle_;
255 };
256
257 TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithVideoOnly) {
258   StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
259
260   SetupFakeUI(true);
261   EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
262   GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
263
264   EXPECT_EQ(host_->audio_devices_.size(), 0u);
265   EXPECT_EQ(host_->video_devices_.size(), 1u);
266 }
267
268 // This test generates two streams with video only using the same render view
269 // id. The same capture device  with the same device and session id is expected
270 // to be used.
271 TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsFromSameRenderId) {
272   StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
273
274   // Generate first stream.
275   SetupFakeUI(true);
276   EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
277   GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
278
279   // Check the latest generated stream.
280   EXPECT_EQ(host_->audio_devices_.size(), 0u);
281   EXPECT_EQ(host_->video_devices_.size(), 1u);
282   const std::string label1 = host_->label_;
283   const std::string device_id1 = host_->video_devices_.front().device.id;
284   const int session_id1 = host_->video_devices_.front().session_id;
285
286   // Generate second stream.
287   SetupFakeUI(true);
288   EXPECT_CALL(*host_.get(),
289               OnStreamGenerated(kRenderId, kPageRequestId + 1, 0, 1));
290   GenerateStreamAndWaitForResult(kRenderId, kPageRequestId + 1, options);
291
292   // Check the latest generated stream.
293   EXPECT_EQ(host_->audio_devices_.size(), 0u);
294   EXPECT_EQ(host_->video_devices_.size(), 1u);
295   const std::string label2 = host_->label_;
296   const std::string device_id2 = host_->video_devices_.front().device.id;
297   int session_id2 = host_->video_devices_.front().session_id;
298   EXPECT_EQ(device_id1, device_id2);
299   EXPECT_EQ(session_id1, session_id2);
300   EXPECT_NE(label1, label2);
301 }
302
303 TEST_F(MediaStreamDispatcherHostTest,
304        GenerateStreamAndOpenDeviceFromSameRenderId) {
305   StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
306
307   // Generate first stream.
308   SetupFakeUI(true);
309   EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
310   GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
311
312   EXPECT_EQ(host_->audio_devices_.size(), 0u);
313   EXPECT_EQ(host_->video_devices_.size(), 1u);
314   const std::string label1 = host_->label_;
315   const std::string device_id1 = host_->video_devices_.front().device.id;
316   const int session_id1 = host_->video_devices_.front().session_id;
317
318   // Generate second stream.
319   OpenVideoDeviceAndWaitForResult(kRenderId, kPageRequestId, device_id1);
320
321   const std::string device_id2 = host_->opened_device_.device.id;
322   const int session_id2 = host_->opened_device_.session_id;
323   const std::string label2 = host_->label_;
324
325   EXPECT_EQ(device_id1, device_id2);
326   EXPECT_NE(session_id1, session_id2);
327   EXPECT_NE(label1, label2);
328 }
329
330
331 // This test generates two streams with video only using two separate render
332 // view ids. The same device id but different session ids are expected.
333 TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsDifferentRenderId) {
334   StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
335
336   // Generate first stream.
337   SetupFakeUI(true);
338   EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
339   GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
340
341   // Check the latest generated stream.
342   EXPECT_EQ(host_->audio_devices_.size(), 0u);
343   EXPECT_EQ(host_->video_devices_.size(), 1u);
344   const std::string label1 = host_->label_;
345   const std::string device_id1 = host_->video_devices_.front().device.id;
346   const int session_id1 = host_->video_devices_.front().session_id;
347
348   // Generate second stream from another render view.
349   SetupFakeUI(true);
350   EXPECT_CALL(*host_.get(),
351               OnStreamGenerated(kRenderId+1, kPageRequestId + 1, 0, 1));
352   GenerateStreamAndWaitForResult(kRenderId+1, kPageRequestId + 1, options);
353
354   // Check the latest generated stream.
355   EXPECT_EQ(host_->audio_devices_.size(), 0u);
356   EXPECT_EQ(host_->video_devices_.size(), 1u);
357   const std::string label2 = host_->label_;
358   const std::string device_id2 = host_->video_devices_.front().device.id;
359   const int session_id2 = host_->video_devices_.front().session_id;
360   EXPECT_EQ(device_id1, device_id2);
361   EXPECT_NE(session_id1, session_id2);
362   EXPECT_NE(label1, label2);
363 }
364
365 // This test request two streams with video only without waiting for the first
366 // stream to be generated before requesting the second.
367 // The same device id and session ids are expected.
368 TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithoutWaiting) {
369   StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
370
371   // Generate first stream.
372   SetupFakeUI(true);
373   EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
374
375   // Generate second stream.
376   EXPECT_CALL(*host_.get(),
377               OnStreamGenerated(kRenderId, kPageRequestId + 1, 0, 1));
378
379   base::RunLoop run_loop1;
380   base::RunLoop run_loop2;
381   host_->OnGenerateStream(kRenderId, kPageRequestId, options,
382                           run_loop1.QuitClosure());
383   host_->OnGenerateStream(kRenderId, kPageRequestId + 1, options,
384                           run_loop2.QuitClosure());
385
386   run_loop1.Run();
387   run_loop2.Run();
388 }
389
390 TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStream) {
391   StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
392
393   SetupFakeUI(true);
394   EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
395   GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
396
397   const std::string device_id = host_->video_devices_.front().device.id;
398   const int session_id =  host_->video_devices_.front().session_id;
399   StreamDeviceInfo video_device_info;
400   EXPECT_TRUE(host_->FindExistingRequestedDeviceInfo(device_id,
401                                                      MEDIA_GENERATE_STREAM,
402                                                      &video_device_info));
403   EXPECT_EQ(video_device_info.device.id, device_id);
404   EXPECT_EQ(video_device_info.session_id, session_id);
405
406   OpenVideoDeviceAndWaitForResult(kRenderId, kPageRequestId, device_id);
407
408   host_->OnStopStreamDevice(kRenderId, device_id);
409
410   EXPECT_FALSE(host_->FindExistingRequestedDeviceInfo(device_id,
411                                                       MEDIA_GENERATE_STREAM,
412                                                       &video_device_info));
413   EXPECT_TRUE(host_->FindExistingRequestedDeviceInfo(device_id,
414                                                      MEDIA_OPEN_DEVICE,
415                                                      &video_device_info));
416 }
417
418 TEST_F(MediaStreamDispatcherHostTest, CancelPendingStreamsOnChannelClosing) {
419   StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
420
421   base::RunLoop run_loop;
422
423   // Create multiple GenerateStream requests.
424   size_t streams = 5;
425   for (size_t i = 1; i <= streams; ++i) {
426     host_->OnGenerateStream(kRenderId, kPageRequestId + i, options,
427                             run_loop.QuitClosure());
428   }
429
430   // Calling OnChannelClosing() to cancel all the pending requests.
431   host_->OnChannelClosing();
432   run_loop.RunUntilIdle();
433 }
434
435 TEST_F(MediaStreamDispatcherHostTest, StopGeneratedStreamsOnChannelClosing) {
436   StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
437
438   // Create first group of streams.
439   size_t generated_streams = 3;
440   for (size_t i = 0; i < generated_streams; ++i) {
441     SetupFakeUI(true);
442     EXPECT_CALL(*host_.get(),
443                 OnStreamGenerated(kRenderId, kPageRequestId + i, 0, 1));
444     GenerateStreamAndWaitForResult(kRenderId, kPageRequestId + i, options);
445   }
446
447   // Calling OnChannelClosing() to cancel all the pending/generated streams.
448   host_->OnChannelClosing();
449   base::RunLoop().RunUntilIdle();
450 }
451
452 TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) {
453   StreamOptions options(MEDIA_NO_SERVICE, MEDIA_DEVICE_VIDEO_CAPTURE);
454
455   base::Closure close_callback;
456   scoped_ptr<MockMediaStreamUIProxy> stream_ui(new MockMediaStreamUIProxy());
457   EXPECT_CALL(*stream_ui, OnStarted(_))
458       .WillOnce(SaveArg<0>(&close_callback));
459   media_stream_manager_->UseFakeUI(stream_ui.PassAs<FakeMediaStreamUIProxy>());
460
461   EXPECT_CALL(*host_.get(), OnStreamGenerated(kRenderId, kPageRequestId, 0, 1));
462   EXPECT_CALL(*host_.get(), OnStopGeneratedStreamFromBrowser(kRenderId));
463   GenerateStreamAndWaitForResult(kRenderId, kPageRequestId, options);
464
465   EXPECT_EQ(host_->audio_devices_.size(), 0u);
466   EXPECT_EQ(host_->video_devices_.size(), 1u);
467
468   ASSERT_FALSE(close_callback.is_null());
469   close_callback.Run();
470   base::RunLoop().RunUntilIdle();
471 }
472
473 };  // namespace content