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