1 // Copyright 2017 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 "chrome/browser/media/chromeos_login_media_access_handler.h"
6 
7 #include <string>
8 
9 #include "base/logging.h"
10 #include "base/values.h"
11 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
12 #include "chrome/browser/chromeos/login/ui/webui_login_view.h"
13 #include "chrome/browser/chromeos/settings/cros_settings.h"
14 #include "chrome/common/url_constants.h"
15 #include "chromeos/settings/cros_settings_names.h"
16 #include "components/content_settings/core/common/content_settings_pattern.h"
17 #include "content/public/browser/render_frame_host.h"
18 #include "url/gurl.h"
19 
ChromeOSLoginMediaAccessHandler()20 ChromeOSLoginMediaAccessHandler::ChromeOSLoginMediaAccessHandler() {}
21 
~ChromeOSLoginMediaAccessHandler()22 ChromeOSLoginMediaAccessHandler::~ChromeOSLoginMediaAccessHandler() {}
23 
SupportsStreamType(content::WebContents * web_contents,const blink::mojom::MediaStreamType type,const extensions::Extension * extension)24 bool ChromeOSLoginMediaAccessHandler::SupportsStreamType(
25     content::WebContents* web_contents,
26     const blink::mojom::MediaStreamType type,
27     const extensions::Extension* extension) {
28   if (!web_contents)
29     return false;
30   chromeos::LoginDisplayHost* host = chromeos::LoginDisplayHost::default_host();
31   return host && web_contents == host->GetOobeWebContents();
32 }
33 
CheckMediaAccessPermission(content::RenderFrameHost * render_frame_host,const GURL & security_origin,blink::mojom::MediaStreamType type,const extensions::Extension * extension)34 bool ChromeOSLoginMediaAccessHandler::CheckMediaAccessPermission(
35     content::RenderFrameHost* render_frame_host,
36     const GURL& security_origin,
37     blink::mojom::MediaStreamType type,
38     const extensions::Extension* extension) {
39   if (type != blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE)
40     return false;
41 
42   // When creating new user (including supervised user), we must be able to use
43   // the camera to capture a user image.
44   if (security_origin.spec() == chrome::kChromeUIOobeURL)
45     return true;
46 
47   const chromeos::CrosSettings* const settings = chromeos::CrosSettings::Get();
48   if (!settings)
49     return false;
50 
51   // The following checks are for SAML logins.
52   const base::Value* const raw_list_value =
53       settings->GetPref(chromeos::kLoginVideoCaptureAllowedUrls);
54   if (!raw_list_value)
55     return false;
56 
57   const base::ListValue* list_value;
58   const bool is_list = raw_list_value->GetAsList(&list_value);
59   DCHECK(is_list);
60   for (const auto& base_value : *list_value) {
61     std::string value;
62     if (base_value.GetAsString(&value)) {
63       const ContentSettingsPattern pattern =
64           ContentSettingsPattern::FromString(value);
65       // Force administrators to specify more-specific patterns by ignoring the
66       // global wildcard pattern.
67       if (pattern == ContentSettingsPattern::Wildcard()) {
68         VLOG(1) << "Ignoring wildcard URL pattern: " << value;
69         continue;
70       }
71       if (pattern.IsValid() && pattern.Matches(security_origin))
72         return true;
73     }
74   }
75   return false;
76 }
77 
HandleRequest(content::WebContents * web_contents,const content::MediaStreamRequest & request,content::MediaResponseCallback callback,const extensions::Extension * extension)78 void ChromeOSLoginMediaAccessHandler::HandleRequest(
79     content::WebContents* web_contents,
80     const content::MediaStreamRequest& request,
81     content::MediaResponseCallback callback,
82     const extensions::Extension* extension) {
83   bool audio_allowed = false;
84   bool video_allowed =
85       request.video_type ==
86           blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE &&
87       CheckMediaAccessPermission(
88           content::RenderFrameHost::FromID(request.render_process_id,
89                                            request.render_frame_id),
90           request.security_origin,
91           blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE, extension);
92 
93   CheckDevicesAndRunCallback(web_contents, request, std::move(callback),
94                              audio_allowed, video_allowed);
95 }
96