1 // Copyright 2014 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
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/metrics/field_trial.h"
10 #include "base/run_loop.h"
11 #include "base/stl_util.h"
12 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
13 #include "chrome/browser/media/webrtc/camera_pan_tilt_zoom_permission_context.h"
14 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
15 #include "chrome/browser/media/webrtc/media_stream_capture_indicator.h"
16 #include "chrome/browser/media/webrtc/media_stream_device_permissions.h"
17 #include "chrome/browser/media/webrtc/permission_bubble_media_access_handler.h"
18 #include "chrome/browser/media/webrtc/webrtc_browsertest_base.h"
19 #include "chrome/browser/permissions/permission_manager_factory.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/ui/browser.h"
22 #include "chrome/browser/ui/tabs/tab_strip_model.h"
23 #include "chrome/common/pref_names.h"
24 #include "chrome/common/webui_url_constants.h"
25 #include "chrome/test/base/ui_test_utils.h"
26 #include "components/content_settings/browser/page_specific_content_settings.h"
27 #include "components/content_settings/core/browser/host_content_settings_map.h"
28 #include "components/permissions/permission_context_base.h"
29 #include "components/permissions/permission_manager.h"
30 #include "components/permissions/permission_request.h"
31 #include "components/permissions/permission_request_manager.h"
32 #include "components/permissions/permission_util.h"
33 #include "components/permissions/test/mock_permission_prompt_factory.h"
34 #include "components/prefs/pref_service.h"
35 #include "components/variations/variations_associated_data.h"
36 #include "content/public/browser/render_frame_host.h"
37 #include "content/public/test/browser_test.h"
38 #include "content/public/test/browser_test_utils.h"
39 #include "content/public/test/mock_render_process_host.h"
40 #include "extensions/common/constants.h"
41 #include "testing/gtest/include/gtest/gtest.h"
42 #include "third_party/blink/public/common/mediastream/media_stream_request.h"
43
44 using content_settings::PageSpecificContentSettings;
45
46 class MediaStreamDevicesControllerTest : public WebRtcTestBase {
47 public:
MediaStreamDevicesControllerTest()48 MediaStreamDevicesControllerTest()
49 : example_audio_id_("fake_audio_dev"),
50 example_video_id_("fake_video_dev"),
51 media_stream_result_(
52 blink::mojom::MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS) {
53 }
54
OnMediaStreamResponse(const blink::MediaStreamDevices & devices,blink::mojom::MediaStreamRequestResult result,std::unique_ptr<content::MediaStreamUI> ui)55 void OnMediaStreamResponse(const blink::MediaStreamDevices& devices,
56 blink::mojom::MediaStreamRequestResult result,
57 std::unique_ptr<content::MediaStreamUI> ui) {
58 EXPECT_EQ(devices.empty(), !ui);
59 media_stream_devices_ = devices;
60 media_stream_result_ = result;
61 std::move(quit_closure_).Run();
62 }
63
64 protected:
65 enum DeviceType { DEVICE_TYPE_AUDIO, DEVICE_TYPE_VIDEO };
66 enum Access { ACCESS_ALLOWED, ACCESS_DENIED };
67
example_url() const68 const GURL& example_url() const { return example_url_; }
69
GetContentSettings()70 PageSpecificContentSettings* GetContentSettings() {
71 return PageSpecificContentSettings::GetForFrame(
72 GetWebContents()->GetMainFrame());
73 }
74
example_audio_id() const75 const std::string& example_audio_id() const { return example_audio_id_; }
example_video_id() const76 const std::string& example_video_id() const { return example_video_id_; }
77
media_stream_result() const78 blink::mojom::MediaStreamRequestResult media_stream_result() const {
79 return media_stream_result_;
80 }
81
RequestPermissions(content::WebContents * web_contents,const content::MediaStreamRequest & request)82 void RequestPermissions(content::WebContents* web_contents,
83 const content::MediaStreamRequest& request) {
84 base::RunLoop run_loop;
85 ASSERT_TRUE(quit_closure_.is_null());
86 quit_closure_ = run_loop.QuitClosure();
87 permission_bubble_media_access_handler_->HandleRequest(
88 web_contents, request,
89 base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
90 base::Unretained(this)),
91 nullptr);
92 run_loop.Run();
93 }
94
95 // Sets the device policy-controlled |access| for |example_url_| to be for the
96 // selected |device_type|.
SetDevicePolicy(DeviceType device_type,Access access)97 void SetDevicePolicy(DeviceType device_type, Access access) {
98 PrefService* prefs = Profile::FromBrowserContext(
99 GetWebContents()->GetBrowserContext())->GetPrefs();
100 const char* policy_name = NULL;
101 switch (device_type) {
102 case DEVICE_TYPE_AUDIO:
103 policy_name = prefs::kAudioCaptureAllowed;
104 break;
105 case DEVICE_TYPE_VIDEO:
106 policy_name = prefs::kVideoCaptureAllowed;
107 break;
108 }
109 prefs->SetBoolean(policy_name, access == ACCESS_ALLOWED);
110 }
111
112 // Set the content settings for mic/cam/ptz.
SetContentSettings(ContentSetting mic_setting,ContentSetting cam_setting,ContentSetting ptz_setting)113 void SetContentSettings(ContentSetting mic_setting,
114 ContentSetting cam_setting,
115 ContentSetting ptz_setting) {
116 HostContentSettingsMap* content_settings =
117 HostContentSettingsMapFactory::GetForProfile(
118 Profile::FromBrowserContext(GetWebContents()->GetBrowserContext()));
119 content_settings->SetContentSettingDefaultScope(
120 example_url_, GURL(), ContentSettingsType::MEDIASTREAM_MIC,
121 mic_setting);
122 content_settings->SetContentSettingDefaultScope(
123 example_url_, GURL(), ContentSettingsType::MEDIASTREAM_CAMERA,
124 cam_setting);
125 content_settings->SetContentSettingDefaultScope(
126 example_url_, GURL(), ContentSettingsType::CAMERA_PAN_TILT_ZOOM,
127 ptz_setting);
128 }
129
130 // Checks whether the devices returned in OnMediaStreamResponse contains a
131 // microphone and/or camera device.
CheckDevicesListContains(blink::mojom::MediaStreamType type)132 bool CheckDevicesListContains(blink::mojom::MediaStreamType type) {
133 for (const auto& device : media_stream_devices_) {
134 if (device.type == type) {
135 return true;
136 }
137 }
138 return false;
139 }
140
GetWebContents()141 content::WebContents* GetWebContents() {
142 return browser()->tab_strip_model()->GetActiveWebContents();
143 }
144
145 // Creates a MediaStreamRequest, asking for those media types, which have a
146 // non-empty id string.
CreateRequestWithType(const std::string & audio_id,const std::string & video_id,bool request_pan_tilt_zoom_permission,blink::MediaStreamRequestType request_type)147 content::MediaStreamRequest CreateRequestWithType(
148 const std::string& audio_id,
149 const std::string& video_id,
150 bool request_pan_tilt_zoom_permission,
151 blink::MediaStreamRequestType request_type) {
152 blink::mojom::MediaStreamType audio_type =
153 audio_id.empty() ? blink::mojom::MediaStreamType::NO_SERVICE
154 : blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE;
155 blink::mojom::MediaStreamType video_type =
156 video_id.empty() ? blink::mojom::MediaStreamType::NO_SERVICE
157 : blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE;
158 EXPECT_EQ(example_url(),
159 GetWebContents()->GetMainFrame()->GetLastCommittedURL());
160 int render_process_id =
161 GetWebContents()->GetMainFrame()->GetProcess()->GetID();
162 int render_frame_id = GetWebContents()->GetMainFrame()->GetRoutingID();
163 return content::MediaStreamRequest(
164 render_process_id, render_frame_id, 0, example_url(), false,
165 request_type, audio_id, video_id, audio_type, video_type,
166 /*disable_local_echo=*/false, request_pan_tilt_zoom_permission);
167 }
168
CreateRequest(const std::string & audio_id,const std::string & video_id,bool request_pan_tilt_zoom_permission)169 content::MediaStreamRequest CreateRequest(
170 const std::string& audio_id,
171 const std::string& video_id,
172 bool request_pan_tilt_zoom_permission) {
173 return CreateRequestWithType(audio_id, video_id,
174 request_pan_tilt_zoom_permission,
175 blink::MEDIA_DEVICE_ACCESS);
176 }
177
InitWithUrl(const GURL & url)178 void InitWithUrl(const GURL& url) {
179 DCHECK(example_url_.is_empty());
180 example_url_ = url;
181 ui_test_utils::NavigateToURL(browser(), example_url_);
182 EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED,
183 GetContentSettings()->GetMicrophoneCameraState());
184 }
185
GetControlSupport() const186 virtual media::VideoCaptureControlSupport GetControlSupport() const {
187 return media::VideoCaptureControlSupport();
188 }
189
prompt_factory()190 permissions::MockPermissionPromptFactory* prompt_factory() {
191 return prompt_factory_.get();
192 }
193
VerifyResultState(blink::mojom::MediaStreamRequestResult result,bool has_audio,bool has_video)194 void VerifyResultState(blink::mojom::MediaStreamRequestResult result,
195 bool has_audio,
196 bool has_video) {
197 EXPECT_EQ(result, media_stream_result());
198 EXPECT_EQ(has_audio,
199 CheckDevicesListContains(
200 blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE));
201 EXPECT_EQ(has_video,
202 CheckDevicesListContains(
203 blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE));
204 }
205
SetUpOnMainThread()206 void SetUpOnMainThread() override {
207 WebRtcTestBase::SetUpOnMainThread();
208
209 ASSERT_TRUE(embedded_test_server()->Start());
210
211 permission_bubble_media_access_handler_ =
212 std::make_unique<PermissionBubbleMediaAccessHandler>();
213
214 permissions::PermissionRequestManager* manager =
215 permissions::PermissionRequestManager::FromWebContents(
216 browser()->tab_strip_model()->GetActiveWebContents());
217 prompt_factory_.reset(
218 new permissions::MockPermissionPromptFactory(manager));
219
220 // Cleanup.
221 media_stream_devices_.clear();
222 media_stream_result_ =
223 blink::mojom::MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS;
224
225 blink::MediaStreamDevices audio_devices;
226 blink::MediaStreamDevice fake_audio_device(
227 blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE, example_audio_id_,
228 "Fake Audio Device");
229 audio_devices.push_back(fake_audio_device);
230 MediaCaptureDevicesDispatcher::GetInstance()->SetTestAudioCaptureDevices(
231 audio_devices);
232
233 blink::MediaStreamDevices video_devices;
234 blink::MediaStreamDevice fake_video_device(
235 blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE, example_video_id_,
236 "Fake Video Device", GetControlSupport(),
237 media::MEDIA_VIDEO_FACING_NONE, base::nullopt);
238 video_devices.push_back(fake_video_device);
239 MediaCaptureDevicesDispatcher::GetInstance()->SetTestVideoCaptureDevices(
240 video_devices);
241 }
242
TearDownOnMainThread()243 void TearDownOnMainThread() override {
244 permission_bubble_media_access_handler_.reset();
245 prompt_factory_.reset();
246
247 WebRtcTestBase::TearDownOnMainThread();
248 }
249
250 GURL example_url_;
251 const std::string example_audio_id_;
252 const std::string example_video_id_;
253
254 blink::MediaStreamDevices media_stream_devices_;
255 blink::mojom::MediaStreamRequestResult media_stream_result_;
256
257 base::OnceClosure quit_closure_;
258
259 std::unique_ptr<permissions::MockPermissionPromptFactory> prompt_factory_;
260
261 std::unique_ptr<PermissionBubbleMediaAccessHandler>
262 permission_bubble_media_access_handler_;
263 };
264
265 class MediaStreamDevicesControllerPtzTest
266 : public MediaStreamDevicesControllerTest,
267 public ::testing::WithParamInterface<media::VideoCaptureControlSupport> {
268 protected:
GetControlSupport() const269 media::VideoCaptureControlSupport GetControlSupport() const override {
270 return GetParam();
271 }
272 };
273
274 // Request and allow microphone access.
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,RequestAndAllowMic)275 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, RequestAndAllowMic) {
276 InitWithUrl(embedded_test_server()->GetURL("/simple.html"));
277 SetDevicePolicy(DEVICE_TYPE_AUDIO, ACCESS_ALLOWED);
278 // Ensure the prompt is accepted if necessary such that tab specific content
279 // settings are updated.
280 prompt_factory()->set_response_type(
281 permissions::PermissionRequestManager::ACCEPT_ALL);
282 RequestPermissions(GetWebContents(),
283 CreateRequest(example_audio_id(), std::string(), false));
284
285 EXPECT_TRUE(GetContentSettings()->IsContentAllowed(
286 ContentSettingsType::MEDIASTREAM_MIC));
287 EXPECT_FALSE(GetContentSettings()->IsContentBlocked(
288 ContentSettingsType::MEDIASTREAM_MIC));
289 EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_ACCESSED,
290 GetContentSettings()->GetMicrophoneCameraState());
291 EXPECT_EQ(example_audio_id(),
292 GetContentSettings()->media_stream_requested_audio_device());
293 EXPECT_EQ(example_audio_id(),
294 GetContentSettings()->media_stream_selected_audio_device());
295 EXPECT_EQ(std::string(),
296 GetContentSettings()->media_stream_requested_video_device());
297 EXPECT_EQ(std::string(),
298 GetContentSettings()->media_stream_selected_video_device());
299 }
300
301 // Request and allow camera access.
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,RequestAndAllowCam)302 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, RequestAndAllowCam) {
303 InitWithUrl(embedded_test_server()->GetURL("/simple.html"));
304 SetDevicePolicy(DEVICE_TYPE_VIDEO, ACCESS_ALLOWED);
305 // Ensure the prompt is accepted if necessary such that tab specific content
306 // settings are updated.
307 prompt_factory()->set_response_type(
308 permissions::PermissionRequestManager::ACCEPT_ALL);
309 RequestPermissions(GetWebContents(),
310 CreateRequest(std::string(), example_video_id(), false));
311
312 EXPECT_TRUE(GetContentSettings()->IsContentAllowed(
313 ContentSettingsType::MEDIASTREAM_CAMERA));
314 EXPECT_FALSE(GetContentSettings()->IsContentBlocked(
315 ContentSettingsType::MEDIASTREAM_CAMERA));
316 EXPECT_EQ(PageSpecificContentSettings::CAMERA_ACCESSED,
317 GetContentSettings()->GetMicrophoneCameraState());
318 EXPECT_EQ(std::string(),
319 GetContentSettings()->media_stream_requested_audio_device());
320 EXPECT_EQ(std::string(),
321 GetContentSettings()->media_stream_selected_audio_device());
322 EXPECT_EQ(example_video_id(),
323 GetContentSettings()->media_stream_requested_video_device());
324 EXPECT_EQ(example_video_id(),
325 GetContentSettings()->media_stream_selected_video_device());
326 }
327
328 // Request and block microphone access.
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,RequestAndBlockMic)329 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, RequestAndBlockMic) {
330 InitWithUrl(embedded_test_server()->GetURL("/simple.html"));
331 SetDevicePolicy(DEVICE_TYPE_AUDIO, ACCESS_DENIED);
332 // Ensure the prompt is accepted if necessary such that tab specific content
333 // settings are updated.
334 prompt_factory()->set_response_type(
335 permissions::PermissionRequestManager::ACCEPT_ALL);
336 RequestPermissions(GetWebContents(),
337 CreateRequest(example_audio_id(), std::string(), false));
338
339 EXPECT_FALSE(GetContentSettings()->IsContentAllowed(
340 ContentSettingsType::MEDIASTREAM_MIC));
341 EXPECT_TRUE(GetContentSettings()->IsContentBlocked(
342 ContentSettingsType::MEDIASTREAM_MIC));
343 EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_ACCESSED |
344 PageSpecificContentSettings::MICROPHONE_BLOCKED,
345 GetContentSettings()->GetMicrophoneCameraState());
346 EXPECT_EQ(example_audio_id(),
347 GetContentSettings()->media_stream_requested_audio_device());
348 EXPECT_EQ(example_audio_id(),
349 GetContentSettings()->media_stream_selected_audio_device());
350 EXPECT_EQ(std::string(),
351 GetContentSettings()->media_stream_requested_video_device());
352 EXPECT_EQ(std::string(),
353 GetContentSettings()->media_stream_selected_video_device());
354 }
355
356 // Request and block camera access.
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,RequestAndBlockCam)357 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, RequestAndBlockCam) {
358 InitWithUrl(embedded_test_server()->GetURL("/simple.html"));
359 SetDevicePolicy(DEVICE_TYPE_VIDEO, ACCESS_DENIED);
360 // Ensure the prompt is accepted if necessary such that tab specific content
361 // settings are updated.
362 prompt_factory()->set_response_type(
363 permissions::PermissionRequestManager::ACCEPT_ALL);
364 RequestPermissions(GetWebContents(),
365 CreateRequest(std::string(), example_video_id(), false));
366
367 EXPECT_FALSE(GetContentSettings()->IsContentAllowed(
368 ContentSettingsType::MEDIASTREAM_CAMERA));
369 EXPECT_TRUE(GetContentSettings()->IsContentBlocked(
370 ContentSettingsType::MEDIASTREAM_CAMERA));
371 EXPECT_EQ(PageSpecificContentSettings::CAMERA_ACCESSED |
372 PageSpecificContentSettings::CAMERA_BLOCKED,
373 GetContentSettings()->GetMicrophoneCameraState());
374 EXPECT_EQ(std::string(),
375 GetContentSettings()->media_stream_requested_audio_device());
376 EXPECT_EQ(std::string(),
377 GetContentSettings()->media_stream_selected_audio_device());
378 EXPECT_EQ(example_video_id(),
379 GetContentSettings()->media_stream_requested_video_device());
380 EXPECT_EQ(example_video_id(),
381 GetContentSettings()->media_stream_selected_video_device());
382 }
383
384 // Request and allow microphone and camera access.
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,RequestAndAllowMicCam)385 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
386 RequestAndAllowMicCam) {
387 InitWithUrl(embedded_test_server()->GetURL("/simple.html"));
388 SetDevicePolicy(DEVICE_TYPE_AUDIO, ACCESS_ALLOWED);
389 SetDevicePolicy(DEVICE_TYPE_VIDEO, ACCESS_ALLOWED);
390 // Ensure the prompt is accepted if necessary such that tab specific content
391 // settings are updated.
392 prompt_factory()->set_response_type(
393 permissions::PermissionRequestManager::ACCEPT_ALL);
394 RequestPermissions(
395 GetWebContents(),
396 CreateRequest(example_audio_id(), example_video_id(), false));
397
398 EXPECT_TRUE(GetContentSettings()->IsContentAllowed(
399 ContentSettingsType::MEDIASTREAM_MIC));
400 EXPECT_FALSE(GetContentSettings()->IsContentBlocked(
401 ContentSettingsType::MEDIASTREAM_MIC));
402 EXPECT_TRUE(GetContentSettings()->IsContentAllowed(
403 ContentSettingsType::MEDIASTREAM_CAMERA));
404 EXPECT_FALSE(GetContentSettings()->IsContentBlocked(
405 ContentSettingsType::MEDIASTREAM_CAMERA));
406 EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_ACCESSED |
407 PageSpecificContentSettings::CAMERA_ACCESSED,
408 GetContentSettings()->GetMicrophoneCameraState());
409 EXPECT_EQ(example_audio_id(),
410 GetContentSettings()->media_stream_requested_audio_device());
411 EXPECT_EQ(example_audio_id(),
412 GetContentSettings()->media_stream_selected_audio_device());
413 EXPECT_EQ(example_video_id(),
414 GetContentSettings()->media_stream_requested_video_device());
415 EXPECT_EQ(example_video_id(),
416 GetContentSettings()->media_stream_selected_video_device());
417 }
418
419 // Request and block microphone and camera access.
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,RequestAndBlockMicCam)420 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
421 RequestAndBlockMicCam) {
422 InitWithUrl(embedded_test_server()->GetURL("/simple.html"));
423 SetDevicePolicy(DEVICE_TYPE_AUDIO, ACCESS_DENIED);
424 SetDevicePolicy(DEVICE_TYPE_VIDEO, ACCESS_DENIED);
425 // Ensure the prompt is accepted if necessary such that tab specific content
426 // settings are updated.
427 prompt_factory()->set_response_type(
428 permissions::PermissionRequestManager::ACCEPT_ALL);
429 RequestPermissions(
430 GetWebContents(),
431 CreateRequest(example_audio_id(), example_video_id(), false));
432
433 EXPECT_FALSE(GetContentSettings()->IsContentAllowed(
434 ContentSettingsType::MEDIASTREAM_MIC));
435 EXPECT_TRUE(GetContentSettings()->IsContentBlocked(
436 ContentSettingsType::MEDIASTREAM_MIC));
437 EXPECT_FALSE(GetContentSettings()->IsContentAllowed(
438 ContentSettingsType::MEDIASTREAM_CAMERA));
439 EXPECT_TRUE(GetContentSettings()->IsContentBlocked(
440 ContentSettingsType::MEDIASTREAM_CAMERA));
441 EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_ACCESSED |
442 PageSpecificContentSettings::MICROPHONE_BLOCKED |
443 PageSpecificContentSettings::CAMERA_ACCESSED |
444 PageSpecificContentSettings::CAMERA_BLOCKED,
445 GetContentSettings()->GetMicrophoneCameraState());
446 EXPECT_EQ(example_audio_id(),
447 GetContentSettings()->media_stream_requested_audio_device());
448 EXPECT_EQ(example_audio_id(),
449 GetContentSettings()->media_stream_selected_audio_device());
450 EXPECT_EQ(example_video_id(),
451 GetContentSettings()->media_stream_requested_video_device());
452 EXPECT_EQ(example_video_id(),
453 GetContentSettings()->media_stream_selected_video_device());
454 }
455
456 // Request microphone and camera access. Camera is denied, thus everything
457 // must be denied.
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,RequestMicCamBlockCam)458 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
459 RequestMicCamBlockCam) {
460 InitWithUrl(embedded_test_server()->GetURL("/simple.html"));
461 SetDevicePolicy(DEVICE_TYPE_AUDIO, ACCESS_ALLOWED);
462 SetDevicePolicy(DEVICE_TYPE_VIDEO, ACCESS_DENIED);
463 // Ensure the prompt is accepted if necessary such that tab specific content
464 // settings are updated.
465 prompt_factory()->set_response_type(
466 permissions::PermissionRequestManager::ACCEPT_ALL);
467 RequestPermissions(
468 GetWebContents(),
469 CreateRequest(example_audio_id(), example_video_id(), false));
470
471 EXPECT_FALSE(GetContentSettings()->IsContentAllowed(
472 ContentSettingsType::MEDIASTREAM_MIC));
473 EXPECT_TRUE(GetContentSettings()->IsContentBlocked(
474 ContentSettingsType::MEDIASTREAM_MIC));
475 EXPECT_FALSE(GetContentSettings()->IsContentAllowed(
476 ContentSettingsType::MEDIASTREAM_CAMERA));
477 EXPECT_TRUE(GetContentSettings()->IsContentBlocked(
478 ContentSettingsType::MEDIASTREAM_CAMERA));
479 EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_ACCESSED |
480 PageSpecificContentSettings::MICROPHONE_BLOCKED |
481 PageSpecificContentSettings::CAMERA_ACCESSED |
482 PageSpecificContentSettings::CAMERA_BLOCKED,
483 GetContentSettings()->GetMicrophoneCameraState());
484 EXPECT_EQ(example_audio_id(),
485 GetContentSettings()->media_stream_requested_audio_device());
486 EXPECT_EQ(example_audio_id(),
487 GetContentSettings()->media_stream_selected_audio_device());
488 EXPECT_EQ(example_video_id(),
489 GetContentSettings()->media_stream_requested_video_device());
490 EXPECT_EQ(example_video_id(),
491 GetContentSettings()->media_stream_selected_video_device());
492 }
493
494 // Request microphone and camera access. Microphone is denied, thus everything
495 // must be denied.
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,RequestMicCamBlockMic)496 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
497 RequestMicCamBlockMic) {
498 InitWithUrl(embedded_test_server()->GetURL("/simple.html"));
499 SetDevicePolicy(DEVICE_TYPE_AUDIO, ACCESS_DENIED);
500 SetDevicePolicy(DEVICE_TYPE_VIDEO, ACCESS_ALLOWED);
501 // Ensure the prompt is accepted if necessary such that tab specific content
502 // settings are updated.
503 prompt_factory()->set_response_type(
504 permissions::PermissionRequestManager::ACCEPT_ALL);
505 RequestPermissions(
506 GetWebContents(),
507 CreateRequest(example_audio_id(), example_video_id(), false));
508
509 EXPECT_FALSE(GetContentSettings()->IsContentAllowed(
510 ContentSettingsType::MEDIASTREAM_MIC));
511 EXPECT_TRUE(GetContentSettings()->IsContentBlocked(
512 ContentSettingsType::MEDIASTREAM_MIC));
513 EXPECT_FALSE(GetContentSettings()->IsContentAllowed(
514 ContentSettingsType::MEDIASTREAM_CAMERA));
515 EXPECT_TRUE(GetContentSettings()->IsContentBlocked(
516 ContentSettingsType::MEDIASTREAM_CAMERA));
517 EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_ACCESSED |
518 PageSpecificContentSettings::MICROPHONE_BLOCKED |
519 PageSpecificContentSettings::CAMERA_ACCESSED |
520 PageSpecificContentSettings::CAMERA_BLOCKED,
521 GetContentSettings()->GetMicrophoneCameraState());
522 EXPECT_EQ(example_audio_id(),
523 GetContentSettings()->media_stream_requested_audio_device());
524 EXPECT_EQ(example_audio_id(),
525 GetContentSettings()->media_stream_selected_audio_device());
526 EXPECT_EQ(example_video_id(),
527 GetContentSettings()->media_stream_requested_video_device());
528 EXPECT_EQ(example_video_id(),
529 GetContentSettings()->media_stream_selected_video_device());
530 }
531
532 // Request microphone access. Requesting camera should not change microphone
533 // state.
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,RequestCamDoesNotChangeMic)534 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
535 RequestCamDoesNotChangeMic) {
536 InitWithUrl(embedded_test_server()->GetURL("/simple.html"));
537 // Request mic and deny.
538 SetDevicePolicy(DEVICE_TYPE_AUDIO, ACCESS_DENIED);
539 // Ensure the prompt is accepted if necessary such that tab specific content
540 // settings are updated.
541 prompt_factory()->set_response_type(
542 permissions::PermissionRequestManager::ACCEPT_ALL);
543 RequestPermissions(GetWebContents(),
544 CreateRequest(example_audio_id(), std::string(), false));
545 EXPECT_FALSE(GetContentSettings()->IsContentAllowed(
546 ContentSettingsType::MEDIASTREAM_MIC));
547 EXPECT_TRUE(GetContentSettings()->IsContentBlocked(
548 ContentSettingsType::MEDIASTREAM_MIC));
549 EXPECT_EQ(example_audio_id(),
550 GetContentSettings()->media_stream_requested_audio_device());
551 EXPECT_EQ(example_audio_id(),
552 GetContentSettings()->media_stream_selected_audio_device());
553
554 // Request cam and allow
555 SetDevicePolicy(DEVICE_TYPE_VIDEO, ACCESS_ALLOWED);
556 RequestPermissions(GetWebContents(),
557 CreateRequest(std::string(), example_video_id(), false));
558 EXPECT_TRUE(GetContentSettings()->IsContentAllowed(
559 ContentSettingsType::MEDIASTREAM_CAMERA));
560 EXPECT_FALSE(GetContentSettings()->IsContentBlocked(
561 ContentSettingsType::MEDIASTREAM_CAMERA));
562 EXPECT_EQ(example_video_id(),
563 GetContentSettings()->media_stream_requested_video_device());
564 EXPECT_EQ(example_video_id(),
565 GetContentSettings()->media_stream_selected_video_device());
566
567 // Mic state should not have changed.
568 EXPECT_FALSE(GetContentSettings()->IsContentAllowed(
569 ContentSettingsType::MEDIASTREAM_MIC));
570 EXPECT_TRUE(GetContentSettings()->IsContentBlocked(
571 ContentSettingsType::MEDIASTREAM_MIC));
572 EXPECT_EQ(example_audio_id(),
573 GetContentSettings()->media_stream_requested_audio_device());
574 EXPECT_EQ(example_audio_id(),
575 GetContentSettings()->media_stream_selected_audio_device());
576 }
577
578 // Denying mic access after camera access should still show the camera as state.
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,DenyMicDoesNotChangeCam)579 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
580 DenyMicDoesNotChangeCam) {
581 InitWithUrl(embedded_test_server()->GetURL("/simple.html"));
582 // Request cam and allow
583 SetDevicePolicy(DEVICE_TYPE_VIDEO, ACCESS_ALLOWED);
584 // Ensure the prompt is accepted if necessary such that tab specific content
585 // settings are updated.
586 prompt_factory()->set_response_type(
587 permissions::PermissionRequestManager::ACCEPT_ALL);
588 RequestPermissions(GetWebContents(),
589 CreateRequest(std::string(), example_video_id(), false));
590 EXPECT_TRUE(GetContentSettings()->IsContentAllowed(
591 ContentSettingsType::MEDIASTREAM_CAMERA));
592 EXPECT_FALSE(GetContentSettings()->IsContentBlocked(
593 ContentSettingsType::MEDIASTREAM_CAMERA));
594 EXPECT_EQ(example_video_id(),
595 GetContentSettings()->media_stream_requested_video_device());
596 EXPECT_EQ(example_video_id(),
597 GetContentSettings()->media_stream_selected_video_device());
598 EXPECT_EQ(PageSpecificContentSettings::CAMERA_ACCESSED,
599 GetContentSettings()->GetMicrophoneCameraState());
600
601 // Simulate that an a video stream is now being captured.
602 blink::MediaStreamDevices video_devices(1);
603 video_devices[0] = blink::MediaStreamDevice(
604 blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE, example_video_id(),
605 example_video_id());
606 MediaCaptureDevicesDispatcher* dispatcher =
607 MediaCaptureDevicesDispatcher::GetInstance();
608 dispatcher->SetTestVideoCaptureDevices(video_devices);
609 std::unique_ptr<content::MediaStreamUI> video_stream_ui =
610 dispatcher->GetMediaStreamCaptureIndicator()->RegisterMediaStream(
611 GetWebContents(), video_devices);
612 video_stream_ui->OnStarted(base::OnceClosure(),
613 content::MediaStreamUI::SourceCallback(),
614 /*label=*/std::string(), /*screen_capture_ids=*/{},
615 content::MediaStreamUI::StateChangeCallback());
616
617 // Request mic and deny.
618 SetDevicePolicy(DEVICE_TYPE_AUDIO, ACCESS_DENIED);
619 // Ensure the prompt is accepted if necessary such that tab specific content
620 // settings are updated.
621 prompt_factory()->set_response_type(
622 permissions::PermissionRequestManager::ACCEPT_ALL);
623 RequestPermissions(GetWebContents(),
624 CreateRequest(example_audio_id(), std::string(), false));
625 EXPECT_FALSE(GetContentSettings()->IsContentAllowed(
626 ContentSettingsType::MEDIASTREAM_MIC));
627 EXPECT_TRUE(GetContentSettings()->IsContentBlocked(
628 ContentSettingsType::MEDIASTREAM_MIC));
629 EXPECT_EQ(example_audio_id(),
630 GetContentSettings()->media_stream_requested_audio_device());
631 EXPECT_EQ(example_audio_id(),
632 GetContentSettings()->media_stream_selected_audio_device());
633
634 // Cam should still be included in the state.
635 EXPECT_TRUE(GetContentSettings()->IsContentAllowed(
636 ContentSettingsType::MEDIASTREAM_CAMERA));
637 EXPECT_FALSE(GetContentSettings()->IsContentBlocked(
638 ContentSettingsType::MEDIASTREAM_CAMERA));
639 EXPECT_EQ(example_video_id(),
640 GetContentSettings()->media_stream_requested_video_device());
641 EXPECT_EQ(example_video_id(),
642 GetContentSettings()->media_stream_selected_video_device());
643 EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_ACCESSED |
644 PageSpecificContentSettings::MICROPHONE_BLOCKED |
645 PageSpecificContentSettings::CAMERA_ACCESSED,
646 GetContentSettings()->GetMicrophoneCameraState());
647
648 // After ending the camera capture, the camera permission is no longer
649 // relevant, so it should no be included in the mic/cam state.
650 video_stream_ui.reset();
651 EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_ACCESSED |
652 PageSpecificContentSettings::MICROPHONE_BLOCKED,
653 GetContentSettings()->GetMicrophoneCameraState());
654 }
655
656 // Stores the ContentSettings inputs for a particular test and has functions
657 // which return the expected outputs for that test.
658 struct ContentSettingsTestData {
659 // The initial value of the mic/cam/ptz content settings.
660 ContentSetting mic;
661 ContentSetting cam;
662 ContentSetting ptz;
663 // Whether the infobar should be accepted if it's shown.
664 bool accept_infobar;
665
666 // Whether the infobar should be displayed to request mic/cam/ptz for the
667 // given content settings inputs.
ExpectMicInfobarContentSettingsTestData668 bool ExpectMicInfobar(
669 const media::VideoCaptureControlSupport& control_support) const {
670 if (cam == CONTENT_SETTING_BLOCK)
671 return false;
672 if (control_support.pan || control_support.tilt || control_support.zoom) {
673 if (ptz == CONTENT_SETTING_BLOCK)
674 return false;
675 }
676 return mic == CONTENT_SETTING_ASK;
677 }
ExpectCamInfobarContentSettingsTestData678 bool ExpectCamInfobar(
679 const media::VideoCaptureControlSupport& control_support) const {
680 if (mic == CONTENT_SETTING_BLOCK)
681 return false;
682 if (control_support.pan || control_support.tilt || control_support.zoom) {
683 if (ptz == CONTENT_SETTING_BLOCK)
684 return false;
685 }
686 return cam == CONTENT_SETTING_ASK;
687 }
ExpectPtzInfobarContentSettingsTestData688 bool ExpectPtzInfobar(
689 const media::VideoCaptureControlSupport& control_support) const {
690 if (mic == CONTENT_SETTING_BLOCK || cam == CONTENT_SETTING_BLOCK)
691 return false;
692 if (!(control_support.pan || control_support.tilt || control_support.zoom))
693 return false;
694 return ptz == CONTENT_SETTING_ASK;
695 }
696
697 // Whether or not the mic/cam/ptz should be allowed after clicking accept/deny
698 // for the given inputs.
ExpectMicAllowedContentSettingsTestData699 bool ExpectMicAllowed() const {
700 return mic == CONTENT_SETTING_ALLOW ||
701 (mic == CONTENT_SETTING_ASK && accept_infobar);
702 }
ExpectCamAllowedContentSettingsTestData703 bool ExpectCamAllowed() const {
704 return cam == CONTENT_SETTING_ALLOW ||
705 (cam == CONTENT_SETTING_ASK && accept_infobar);
706 }
ExpectPtzAllowedContentSettingsTestData707 bool ExpectPtzAllowed() const {
708 return ptz == CONTENT_SETTING_ALLOW ||
709 (ptz == CONTENT_SETTING_ASK && accept_infobar);
710 }
711
712 // The expected media stream result after clicking accept/deny for the given
713 // inputs.
ExpectedMediaStreamResultContentSettingsTestData714 blink::mojom::MediaStreamRequestResult ExpectedMediaStreamResult(
715 const media::VideoCaptureControlSupport& control_support) const {
716 if (ExpectMicAllowed() && ExpectCamAllowed()) {
717 if (!control_support.pan && !control_support.tilt &&
718 !control_support.zoom) {
719 return blink::mojom::MediaStreamRequestResult::OK;
720 }
721 if (ptz != CONTENT_SETTING_BLOCK) {
722 return blink::mojom::MediaStreamRequestResult::OK;
723 }
724 }
725 return blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED;
726 }
727 };
728
729 // Test all combinations of cam/mic content settings. Then tests the result of
730 // clicking both accept/deny on the infobar. Both cam/mic are requested.
IN_PROC_BROWSER_TEST_P(MediaStreamDevicesControllerPtzTest,ContentSettings)731 IN_PROC_BROWSER_TEST_P(MediaStreamDevicesControllerPtzTest, ContentSettings) {
732 InitWithUrl(embedded_test_server()->GetURL("/simple.html"));
733 static const ContentSettingsTestData tests[] = {
734 // Settings that won't result in an infobar.
735 {CONTENT_SETTING_ALLOW, CONTENT_SETTING_ALLOW, CONTENT_SETTING_ALLOW,
736 false},
737 {CONTENT_SETTING_ALLOW, CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK,
738 false},
739 {CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK, CONTENT_SETTING_ALLOW,
740 false},
741 {CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK, CONTENT_SETTING_BLOCK,
742 false},
743 {CONTENT_SETTING_BLOCK, CONTENT_SETTING_ALLOW, CONTENT_SETTING_ALLOW,
744 false},
745 {CONTENT_SETTING_BLOCK, CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK,
746 false},
747 {CONTENT_SETTING_BLOCK, CONTENT_SETTING_BLOCK, CONTENT_SETTING_ALLOW,
748 false},
749 {CONTENT_SETTING_BLOCK, CONTENT_SETTING_BLOCK, CONTENT_SETTING_BLOCK,
750 false},
751 {CONTENT_SETTING_BLOCK, CONTENT_SETTING_ASK, CONTENT_SETTING_ASK, false},
752 {CONTENT_SETTING_ASK, CONTENT_SETTING_BLOCK, CONTENT_SETTING_ASK, false},
753 {CONTENT_SETTING_ASK, CONTENT_SETTING_ASK, CONTENT_SETTING_BLOCK, false},
754
755 // Settings that will result in an infobar. Test both accept and deny.
756 {CONTENT_SETTING_ALLOW, CONTENT_SETTING_ALLOW, CONTENT_SETTING_ASK,
757 false},
758 {CONTENT_SETTING_ALLOW, CONTENT_SETTING_ALLOW, CONTENT_SETTING_ASK, true},
759
760 {CONTENT_SETTING_ALLOW, CONTENT_SETTING_ASK, CONTENT_SETTING_ALLOW,
761 false},
762 {CONTENT_SETTING_ALLOW, CONTENT_SETTING_ASK, CONTENT_SETTING_ALLOW, true},
763
764 {CONTENT_SETTING_ASK, CONTENT_SETTING_ALLOW, CONTENT_SETTING_ASK, false},
765 {CONTENT_SETTING_ASK, CONTENT_SETTING_ALLOW, CONTENT_SETTING_ASK, true},
766
767 {CONTENT_SETTING_ALLOW, CONTENT_SETTING_ASK, CONTENT_SETTING_ASK, false},
768 {CONTENT_SETTING_ALLOW, CONTENT_SETTING_ASK, CONTENT_SETTING_ASK, true},
769
770 {CONTENT_SETTING_ASK, CONTENT_SETTING_ALLOW, CONTENT_SETTING_ASK, false},
771 {CONTENT_SETTING_ASK, CONTENT_SETTING_ALLOW, CONTENT_SETTING_ASK, true},
772
773 {CONTENT_SETTING_ASK, CONTENT_SETTING_ASK, CONTENT_SETTING_ALLOW, false},
774 {CONTENT_SETTING_ASK, CONTENT_SETTING_ASK, CONTENT_SETTING_ALLOW, true},
775
776 {CONTENT_SETTING_ASK, CONTENT_SETTING_ASK, CONTENT_SETTING_ASK, false},
777 {CONTENT_SETTING_ASK, CONTENT_SETTING_ASK, CONTENT_SETTING_ASK, true},
778 };
779
780 // Prevent automatic camera permission change when camera PTZ gets updated.
781 CameraPanTiltZoomPermissionContext* camera_pan_tilt_zoom_permission_context =
782 static_cast<CameraPanTiltZoomPermissionContext*>(
783 PermissionManagerFactory::GetForProfile(
784 Profile::FromBrowserContext(
785 GetWebContents()->GetBrowserContext()))
786 ->GetPermissionContextForTesting(
787 ContentSettingsType::CAMERA_PAN_TILT_ZOOM));
788 HostContentSettingsMap* content_settings =
789 HostContentSettingsMapFactory::GetForProfile(
790 Profile::FromBrowserContext(GetWebContents()->GetBrowserContext()));
791 content_settings->RemoveObserver(camera_pan_tilt_zoom_permission_context);
792
793 const auto& control_support = GetControlSupport();
794 for (auto& test : tests) {
795 SetContentSettings(test.mic, test.cam, test.ptz);
796
797 prompt_factory()->ResetCounts();
798
799 // Accept or deny the infobar if it's showing.
800 if (test.ExpectMicInfobar(control_support) ||
801 test.ExpectCamInfobar(control_support) ||
802 test.ExpectPtzInfobar(control_support)) {
803 if (test.accept_infobar) {
804 prompt_factory()->set_response_type(
805 permissions::PermissionRequestManager::ACCEPT_ALL);
806 } else {
807 prompt_factory()->set_response_type(
808 permissions::PermissionRequestManager::DENY_ALL);
809 }
810 } else {
811 prompt_factory()->set_response_type(
812 permissions::PermissionRequestManager::NONE);
813 }
814 RequestPermissions(
815 GetWebContents(),
816 CreateRequest(example_audio_id(), example_video_id(), true));
817
818 ASSERT_LE(prompt_factory()->TotalRequestCount(), 3);
819 EXPECT_EQ(
820 test.ExpectMicInfobar(control_support),
821 prompt_factory()->RequestTypeSeen(
822 permissions::PermissionRequestType::PERMISSION_MEDIASTREAM_MIC));
823 EXPECT_EQ(
824 test.ExpectCamInfobar(control_support),
825 prompt_factory()->RequestTypeSeen(
826 permissions::PermissionRequestType::PERMISSION_MEDIASTREAM_CAMERA));
827 EXPECT_EQ(
828 test.ExpectPtzInfobar(control_support),
829 prompt_factory()->RequestTypeSeen(permissions::PermissionRequestType::
830 PERMISSION_CAMERA_PAN_TILT_ZOOM));
831
832 // Check the media stream result is expected and the devices returned are
833 // expected;
834 VerifyResultState(test.ExpectedMediaStreamResult(control_support),
835 test.ExpectMicAllowed() && test.ExpectCamAllowed() &&
836 (!(control_support.pan || control_support.tilt ||
837 control_support.zoom) ||
838 test.ptz != CONTENT_SETTING_BLOCK),
839 test.ExpectMicAllowed() && test.ExpectCamAllowed() &&
840 (!(control_support.pan || control_support.tilt ||
841 control_support.zoom) ||
842 test.ptz != CONTENT_SETTING_BLOCK));
843 }
844 }
845
846 INSTANTIATE_TEST_SUITE_P(
847 All,
848 MediaStreamDevicesControllerPtzTest,
849 ::testing::Values(media::VideoCaptureControlSupport({false, false, false}),
850 media::VideoCaptureControlSupport({false, false, true}),
851 media::VideoCaptureControlSupport({true, true, true})));
852
853 // Request and allow camera access on WebUI pages without prompting.
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,WebUIRequestAndAllowCam)854 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
855 WebUIRequestAndAllowCam) {
856 InitWithUrl(GURL(chrome::kChromeUIVersionURL));
857 RequestPermissions(GetWebContents(),
858 CreateRequest(std::string(), example_video_id(), false));
859
860 ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
861
862 VerifyResultState(blink::mojom::MediaStreamRequestResult::OK, false, true);
863 }
864
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,ExtensionRequestMicCam)865 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
866 ExtensionRequestMicCam) {
867 std::string pdf_extension_page = std::string(extensions::kExtensionScheme) +
868 "://" + extension_misc::kPdfExtensionId +
869 "/index.html";
870 InitWithUrl(GURL(pdf_extension_page));
871 // Test that a prompt is required.
872 prompt_factory()->set_response_type(
873 permissions::PermissionRequestManager::ACCEPT_ALL);
874 RequestPermissions(
875 GetWebContents(),
876 CreateRequest(example_audio_id(), example_video_id(), false));
877 ASSERT_EQ(2, prompt_factory()->TotalRequestCount());
878 ASSERT_TRUE(prompt_factory()->RequestTypeSeen(
879 permissions::PermissionRequestType::PERMISSION_MEDIASTREAM_CAMERA));
880 ASSERT_TRUE(prompt_factory()->RequestTypeSeen(
881 permissions::PermissionRequestType::PERMISSION_MEDIASTREAM_MIC));
882
883 VerifyResultState(blink::mojom::MediaStreamRequestResult::OK, true, true);
884
885 // Check that re-requesting allows without prompting.
886 prompt_factory()->ResetCounts();
887 RequestPermissions(
888 GetWebContents(),
889 CreateRequest(example_audio_id(), example_video_id(), false));
890 ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
891
892 VerifyResultState(blink::mojom::MediaStreamRequestResult::OK, true, true);
893 }
894
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,PepperRequestInsecure)895 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
896 PepperRequestInsecure) {
897 InitWithUrl(GURL("http://www.example.com"));
898
899 prompt_factory()->set_response_type(
900 permissions::PermissionRequestManager::ACCEPT_ALL);
901
902 RequestPermissions(
903 GetWebContents(),
904 CreateRequestWithType(example_audio_id(), example_video_id(), false,
905 blink::MEDIA_OPEN_DEVICE_PEPPER_ONLY));
906 ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
907
908 VerifyResultState(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
909 false, false);
910 }
911
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,WebContentsDestroyed)912 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, WebContentsDestroyed) {
913 InitWithUrl(embedded_test_server()->GetURL("/simple.html"));
914
915 prompt_factory()->set_response_type(
916 permissions::PermissionRequestManager::ACCEPT_ALL);
917
918 content::MediaStreamRequest request =
919 CreateRequest(example_audio_id(), example_video_id(), false);
920 // Simulate a destroyed RenderFrameHost.
921 request.render_frame_id = 0;
922 request.render_process_id = 0;
923
924 RequestPermissions(nullptr, request);
925 ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
926
927 VerifyResultState(
928 blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, false,
929 false);
930 }
931
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,WebContentsDestroyedDuringRequest)932 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
933 WebContentsDestroyedDuringRequest) {
934 InitWithUrl(embedded_test_server()->GetURL("/simple.html"));
935 ui_test_utils::NavigateToURLWithDisposition(
936 browser(), GURL("about:blank"), WindowOpenDisposition::NEW_BACKGROUND_TAB,
937 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
938
939 prompt_factory()->set_response_type(
940 permissions::PermissionRequestManager::ACCEPT_ALL);
941
942 content::WebContents* prompt_contents = GetWebContents();
943 const int prompt_contents_index =
944 browser()->tab_strip_model()->GetIndexOfWebContents(prompt_contents);
945
946 // Now request permissions, but before the callback is asynchronously called,
947 // destroy the tab.
948 permission_bubble_media_access_handler_->HandleRequest(
949 prompt_contents,
950 CreateRequest(example_audio_id(), example_video_id(), false),
951 base::BindOnce([](const blink::MediaStreamDevices& devices,
952 blink::mojom::MediaStreamRequestResult result,
953 std::unique_ptr<content::MediaStreamUI> ui) {
954 ADD_FAILURE() << " this callback shouldn't be reached";
955 }),
956 nullptr);
957 // Since the mock prompt factory holds a reference to the
958 // PermissionRequestManager for the WebContents and uses that reference in its
959 // destructor, it has to be destroyed before the tab.
960 prompt_factory_.reset();
961 ASSERT_TRUE(browser()->tab_strip_model()->CloseWebContentsAt(
962 prompt_contents_index, TabStripModel::CloseTypes::CLOSE_USER_GESTURE));
963 base::RunLoop().RunUntilIdle();
964
965 VerifyResultState(
966 blink::mojom::MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS, false,
967 false);
968 }
969
970 // Request and block microphone and camera access with kill switch.
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,RequestAndKillSwitchMicCam)971 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
972 RequestAndKillSwitchMicCam) {
973 std::map<std::string, std::string> params;
974 params[permissions::PermissionUtil::GetPermissionString(
975 ContentSettingsType::MEDIASTREAM_MIC)] =
976 permissions::PermissionContextBase::kPermissionsKillSwitchBlockedValue;
977 params[permissions::PermissionUtil::GetPermissionString(
978 ContentSettingsType::MEDIASTREAM_CAMERA)] =
979 permissions::PermissionContextBase::kPermissionsKillSwitchBlockedValue;
980 variations::AssociateVariationParams(
981 permissions::PermissionContextBase::kPermissionsKillSwitchFieldStudy,
982 "TestGroup", params);
983 base::FieldTrialList::CreateFieldTrial(
984 permissions::PermissionContextBase::kPermissionsKillSwitchFieldStudy,
985 "TestGroup");
986 InitWithUrl(embedded_test_server()->GetURL("/simple.html"));
987 SetDevicePolicy(DEVICE_TYPE_AUDIO, ACCESS_ALLOWED);
988 SetDevicePolicy(DEVICE_TYPE_VIDEO, ACCESS_ALLOWED);
989 RequestPermissions(
990 GetWebContents(),
991 CreateRequest(example_audio_id(), example_video_id(), false));
992
993 ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
994 VerifyResultState(blink::mojom::MediaStreamRequestResult::KILL_SWITCH_ON,
995 false, false);
996 }
997
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,RequestCamAndMicBlockedByFeaturePolicy)998 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
999 RequestCamAndMicBlockedByFeaturePolicy) {
1000 InitWithUrl(embedded_test_server()->GetURL("/iframe_blank.html"));
1001
1002 // Create a cross-origin request by using localhost as the iframe origin.
1003 GURL::Replacements replace_host;
1004 replace_host.SetHostStr("localhost");
1005 GURL cross_origin_url = embedded_test_server()
1006 ->GetURL("/simple.html")
1007 .ReplaceComponents(replace_host);
1008 content::NavigateIframeToURL(GetWebContents(), "test",
1009 GURL(cross_origin_url));
1010 content::RenderFrameHost* child_frame =
1011 ChildFrameAt(GetWebContents()->GetMainFrame(), 0);
1012
1013 content::MediaStreamRequest request =
1014 CreateRequest(example_audio_id(), example_video_id(), false);
1015 // Make the child frame the source of the request.
1016 request.render_process_id = child_frame->GetProcess()->GetID();
1017 request.render_frame_id = child_frame->GetRoutingID();
1018 RequestPermissions(GetWebContents(), request);
1019
1020 ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
1021
1022 VerifyResultState(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
1023 false, false);
1024 EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED,
1025 GetContentSettings()->GetMicrophoneCameraState());
1026 }
1027
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,RequestCamBlockedByFeaturePolicy)1028 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
1029 RequestCamBlockedByFeaturePolicy) {
1030 InitWithUrl(embedded_test_server()->GetURL("/iframe_blank.html"));
1031
1032 // Create a cross-origin request by using localhost as the iframe origin.
1033 GURL::Replacements replace_host;
1034 replace_host.SetHostStr("localhost");
1035 GURL cross_origin_url = embedded_test_server()
1036 ->GetURL("/simple.html")
1037 .ReplaceComponents(replace_host);
1038 content::NavigateIframeToURL(GetWebContents(), "test",
1039 GURL(cross_origin_url));
1040 content::RenderFrameHost* child_frame =
1041 ChildFrameAt(GetWebContents()->GetMainFrame(), 0);
1042
1043 content::MediaStreamRequest request =
1044 CreateRequest(std::string(), example_video_id(), false);
1045 // Make the child frame the source of the request.
1046 request.render_process_id = child_frame->GetProcess()->GetID();
1047 request.render_frame_id = child_frame->GetRoutingID();
1048 RequestPermissions(GetWebContents(), request);
1049
1050 ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
1051
1052 VerifyResultState(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
1053 false, false);
1054 EXPECT_EQ(PageSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED,
1055 GetContentSettings()->GetMicrophoneCameraState());
1056 }
1057
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,PepperAudioRequestNoCamera)1058 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
1059 PepperAudioRequestNoCamera) {
1060 MediaCaptureDevicesDispatcher::GetInstance()->SetTestVideoCaptureDevices({});
1061 InitWithUrl(GURL(chrome::kChromeUIVersionURL));
1062 RequestPermissions(
1063 GetWebContents(),
1064 CreateRequestWithType(example_audio_id(), std::string(), false,
1065 blink::MEDIA_OPEN_DEVICE_PEPPER_ONLY));
1066 VerifyResultState(blink::mojom::MediaStreamRequestResult::OK, true, false);
1067 }
1068
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,PepperVideoRequestNoMic)1069 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
1070 PepperVideoRequestNoMic) {
1071 MediaCaptureDevicesDispatcher::GetInstance()->SetTestAudioCaptureDevices({});
1072 InitWithUrl(GURL(chrome::kChromeUIVersionURL));
1073 RequestPermissions(
1074 GetWebContents(),
1075 CreateRequestWithType(std::string(), example_video_id(), false,
1076 blink::MEDIA_OPEN_DEVICE_PEPPER_ONLY));
1077 VerifyResultState(blink::mojom::MediaStreamRequestResult::OK, false, true);
1078 }
1079