- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / media / device_request_message_filter_unittest.cc
1 // Copyright 2013 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 "base/strings/string_number_conversions.h"
6 #include "content/browser/renderer_host/media/device_request_message_filter.h"
7 #include "content/browser/renderer_host/media/media_stream_manager.h"
8 #include "content/common/media/media_stream_messages.h"
9 #include "content/public/browser/media_device_id.h"
10 #include "content/public/test/mock_resource_context.h"
11 #include "content/public/test/test_browser_thread.h"
12 #include "testing/gmock/include/gmock/gmock.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 using ::testing::_;
16 using ::testing::Invoke;
17
18 namespace content {
19
20 static const std::string kAudioLabel = "audio_label";
21 static const std::string kVideoLabel = "video_label";
22
23 class MockMediaStreamManager : public MediaStreamManager {
24  public:
25   MockMediaStreamManager() {}
26
27   virtual ~MockMediaStreamManager() {}
28
29   MOCK_METHOD6(EnumerateDevices,
30                std::string(MediaStreamRequester* requester,
31                            int render_process_id,
32                            int render_view_id,
33                            int page_request_id,
34                            MediaStreamType type,
35                            const GURL& security_origin));
36   MOCK_METHOD1(CancelRequest, void(const std::string& label));
37
38   std::string DoEnumerateDevices(MediaStreamRequester* requester,
39                                  int render_process_id,
40                                  int render_view_id,
41                                  int page_request_id,
42                                  MediaStreamType type,
43                                  const GURL& security_origin) {
44     if (type == MEDIA_DEVICE_AUDIO_CAPTURE) {
45       return kAudioLabel;
46     } else {
47       return kVideoLabel;
48     }
49   }
50 };
51
52 class MockDeviceRequestMessageFilter : public DeviceRequestMessageFilter {
53  public:
54   MockDeviceRequestMessageFilter(MockResourceContext* context,
55                                  MockMediaStreamManager* manager)
56       : DeviceRequestMessageFilter(context, manager), received_id_(-1) {}
57   StreamDeviceInfoArray requested_devices() { return requested_devices_; }
58   int received_id() { return received_id_; }
59
60  private:
61   virtual ~MockDeviceRequestMessageFilter() {}
62
63   // Override the Send() method to intercept the message that we're sending to
64   // the renderer.
65   virtual bool Send(IPC::Message* reply_msg) OVERRIDE {
66     CHECK(reply_msg);
67
68     bool handled = true;
69     IPC_BEGIN_MESSAGE_MAP(MockDeviceRequestMessageFilter, *reply_msg)
70       IPC_MESSAGE_HANDLER(MediaStreamMsg_GetSourcesACK, SaveDevices)
71       IPC_MESSAGE_UNHANDLED(handled = false)
72     IPC_END_MESSAGE_MAP()
73     EXPECT_TRUE(handled);
74
75     delete reply_msg;
76     return true;
77   }
78
79   void SaveDevices(int request_id, const StreamDeviceInfoArray& devices) {
80     received_id_ = request_id;
81     requested_devices_ = devices;
82   }
83
84   int received_id_;
85   StreamDeviceInfoArray requested_devices_;
86 };
87
88 class DeviceRequestMessageFilterTest : public testing::Test {
89  public:
90   DeviceRequestMessageFilterTest() : next_device_id_(0) {}
91
92   void RunTest(int number_audio_devices, int number_video_devices) {
93     AddAudioDevices(number_audio_devices);
94     AddVideoDevices(number_video_devices);
95     GURL origin("https://test.com");
96     EXPECT_CALL(*media_stream_manager_,
97                 EnumerateDevices(_, _, _, _, MEDIA_DEVICE_AUDIO_CAPTURE, _))
98         .Times(1);
99     EXPECT_CALL(*media_stream_manager_,
100                 EnumerateDevices(_, _, _, _, MEDIA_DEVICE_VIDEO_CAPTURE, _))
101         .Times(1);
102     // Send message to get devices. Should trigger 2 EnumerateDevice() requests.
103     const int kRequestId = 123;
104     SendGetSourcesMessage(kRequestId, origin);
105
106     // Run audio callback. Because there's still an outstanding video request,
107     // this should not populate |message|.
108     FireAudioDeviceCallback();
109     EXPECT_EQ(0u, host_->requested_devices().size());
110
111     // After the video device callback is fired, |message| should be populated.
112     EXPECT_CALL(*media_stream_manager_, CancelRequest(kAudioLabel))
113         .Times(1);
114     EXPECT_CALL(*media_stream_manager_, CancelRequest(kVideoLabel))
115         .Times(1);
116     FireVideoDeviceCallback();
117     EXPECT_EQ(static_cast<size_t>(number_audio_devices + number_video_devices),
118               host_->requested_devices().size());
119
120     EXPECT_EQ(kRequestId, host_->received_id());
121     // Check to make sure no devices have raw ids.
122     EXPECT_FALSE(DoesContainRawIds(host_->requested_devices()));
123
124     // Check to make sure every GUID produced matches a raw device id.
125     EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->requested_devices(), origin));
126   }
127
128   bool AreLabelsPresent(MediaStreamType type) {
129     const StreamDeviceInfoArray& devices = host_->requested_devices();
130     for (size_t i = 0; i < devices.size(); i++) {
131       if (devices[i].device.type == type && !devices[i].device.name.empty())
132         return true;
133     }
134     return false;
135   }
136
137  protected:
138   virtual ~DeviceRequestMessageFilterTest() {}
139
140   virtual void SetUp() OVERRIDE {
141     message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
142     io_thread_.reset(
143         new TestBrowserThread(BrowserThread::IO, message_loop_.get()));
144
145     media_stream_manager_.reset(new MockMediaStreamManager());
146     ON_CALL(*media_stream_manager_, EnumerateDevices(_, _, _, _, _, _))
147         .WillByDefault(Invoke(media_stream_manager_.get(),
148                               &MockMediaStreamManager::DoEnumerateDevices));
149
150     resource_context_.reset(new MockResourceContext(NULL));
151     host_ = new MockDeviceRequestMessageFilter(resource_context_.get(),
152                                                media_stream_manager_.get());
153   }
154
155   scoped_refptr<MockDeviceRequestMessageFilter> host_;
156   scoped_ptr<MockMediaStreamManager> media_stream_manager_;
157   scoped_ptr<MockResourceContext> resource_context_;
158   StreamDeviceInfoArray physical_audio_devices_;
159   StreamDeviceInfoArray physical_video_devices_;
160   scoped_ptr<base::MessageLoop> message_loop_;
161   scoped_ptr<TestBrowserThread> io_thread_;
162
163  private:
164   void AddAudioDevices(int number_of_devices) {
165     for (int i = 0; i < number_of_devices; i++) {
166       physical_audio_devices_.push_back(
167           StreamDeviceInfo(
168               MEDIA_DEVICE_AUDIO_CAPTURE,
169               "/dev/audio/" + base::IntToString(next_device_id_),
170               "Audio Device" + base::IntToString(next_device_id_)));
171       next_device_id_++;
172     }
173   }
174
175   void AddVideoDevices(int number_of_devices) {
176     for (int i = 0; i < number_of_devices; i++) {
177       physical_video_devices_.push_back(
178           StreamDeviceInfo(
179               MEDIA_DEVICE_VIDEO_CAPTURE,
180               "/dev/video/" + base::IntToString(next_device_id_),
181               "Video Device" + base::IntToString(next_device_id_)));
182       next_device_id_++;
183     }
184   }
185
186   void SendGetSourcesMessage(int request_id, const GURL& origin) {
187     // Since we're not actually sending IPC messages, this is a throw-away
188     // value.
189     bool message_was_ok;
190     host_->OnMessageReceived(MediaStreamHostMsg_GetSources(request_id, origin),
191                              &message_was_ok);
192   }
193
194   void FireAudioDeviceCallback() {
195     host_->DevicesEnumerated(kAudioLabel, physical_audio_devices_);
196   }
197
198   void FireVideoDeviceCallback() {
199     host_->DevicesEnumerated(kVideoLabel, physical_video_devices_);
200   }
201
202   bool DoesContainRawIds(const StreamDeviceInfoArray& devices) {
203     for (size_t i = 0; i < devices.size(); i++) {
204       for (size_t j = 0; j < physical_audio_devices_.size(); ++j) {
205         if (physical_audio_devices_[j].device.id == devices[i].device.id)
206           return true;
207       }
208       for (size_t j = 0; j < physical_video_devices_.size(); ++j) {
209         if (physical_video_devices_[j].device.id == devices[i].device.id)
210           return true;
211       }
212     }
213     return false;
214   }
215
216   bool DoesEveryDeviceMapToRawId(const StreamDeviceInfoArray& devices,
217                                  const GURL& origin) {
218     for (size_t i = 0; i < devices.size(); i++) {
219       bool found_match = false;
220       for (size_t j = 0; j < physical_audio_devices_.size(); ++j) {
221         if (content::DoesMediaDeviceIDMatchHMAC(
222                 origin,
223                 devices[i].device.id,
224                 physical_audio_devices_[j].device.id)) {
225           EXPECT_FALSE(found_match);
226           found_match = true;
227         }
228       }
229       for (size_t j = 0; j < physical_video_devices_.size(); ++j) {
230         if (content::DoesMediaDeviceIDMatchHMAC(
231                 origin,
232                 devices[i].device.id,
233                 physical_video_devices_[j].device.id)) {
234           EXPECT_FALSE(found_match);
235           found_match = true;
236         }
237       }
238       if (!found_match)
239         return false;
240     }
241     return true;
242   }
243
244   int next_device_id_;
245 };
246
247 TEST_F(DeviceRequestMessageFilterTest, TestGetSources_AudioAndVideoDevices) {
248   // Runs through test with 1 audio and 1 video device.
249   RunTest(1, 1);
250 }
251
252 TEST_F(DeviceRequestMessageFilterTest,
253        TestGetSources_MultipleAudioAndVideoDevices) {
254   // Runs through test with 3 audio devices and 2 video devices.
255   RunTest(3, 2);
256 }
257
258 TEST_F(DeviceRequestMessageFilterTest, TestGetSources_NoVideoDevices) {
259   // Runs through test with 4 audio devices and 0 video devices.
260   RunTest(4, 0);
261 }
262
263 TEST_F(DeviceRequestMessageFilterTest, TestGetSources_NoAudioDevices) {
264   // Runs through test with 0 audio devices and 3 video devices.
265   RunTest(0, 3);
266 }
267
268 TEST_F(DeviceRequestMessageFilterTest, TestGetSources_NoDevices) {
269   // Runs through test with no devices.
270   RunTest(0, 0);
271 }
272
273 TEST_F(DeviceRequestMessageFilterTest, TestGetSources_DenyMicDenyCamera) {
274   resource_context_->set_mic_access(false);
275   resource_context_->set_camera_access(false);
276   RunTest(3, 3);
277   EXPECT_FALSE(AreLabelsPresent(MEDIA_DEVICE_AUDIO_CAPTURE));
278   EXPECT_FALSE(AreLabelsPresent(MEDIA_DEVICE_VIDEO_CAPTURE));
279 }
280
281 TEST_F(DeviceRequestMessageFilterTest, TestGetSources_AllowMicDenyCamera) {
282   resource_context_->set_mic_access(true);
283   resource_context_->set_camera_access(false);
284   RunTest(3, 3);
285   EXPECT_TRUE(AreLabelsPresent(MEDIA_DEVICE_AUDIO_CAPTURE));
286   EXPECT_FALSE(AreLabelsPresent(MEDIA_DEVICE_VIDEO_CAPTURE));
287 }
288
289 TEST_F(DeviceRequestMessageFilterTest, TestGetSources_DenyMicAllowCamera) {
290   resource_context_->set_mic_access(false);
291   resource_context_->set_camera_access(true);
292   RunTest(3, 3);
293   EXPECT_FALSE(AreLabelsPresent(MEDIA_DEVICE_AUDIO_CAPTURE));
294   EXPECT_TRUE(AreLabelsPresent(MEDIA_DEVICE_VIDEO_CAPTURE));
295 }
296
297 TEST_F(DeviceRequestMessageFilterTest, TestGetSources_AllowMicAllowCamera) {
298   resource_context_->set_mic_access(true);
299   resource_context_->set_camera_access(true);
300   RunTest(3, 3);
301   EXPECT_TRUE(AreLabelsPresent(MEDIA_DEVICE_AUDIO_CAPTURE));
302   EXPECT_TRUE(AreLabelsPresent(MEDIA_DEVICE_VIDEO_CAPTURE));
303 }
304
305 };  // namespace content