Fix build break
[chromium-blink-merge.git] / chrome / browser / media / media_stream_devices_controller.cc
blobd8a8a30ebdd306459f7a06f1861d1c8690597755
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/media/media_stream_devices_controller.h"
7 #include "base/command_line.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/values.h"
10 #include "chrome/browser/content_settings/content_settings_provider.h"
11 #include "chrome/browser/content_settings/host_content_settings_map.h"
12 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
13 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
14 #include "chrome/browser/prefs/scoped_user_pref_update.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "chrome/common/content_settings.h"
19 #include "chrome/common/pref_names.h"
20 #include "components/user_prefs/pref_registry_syncable.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/common/media_stream_request.h"
24 using content::BrowserThread;
26 namespace {
28 bool HasAnyAvailableDevice() {
29 const content::MediaStreamDevices& audio_devices =
30 MediaCaptureDevicesDispatcher::GetInstance()->GetAudioCaptureDevices();
31 const content::MediaStreamDevices& video_devices =
32 MediaCaptureDevicesDispatcher::GetInstance()->GetVideoCaptureDevices();
34 return !audio_devices.empty() || !video_devices.empty();
37 } // namespace
39 MediaStreamDevicesController::MediaStreamDevicesController(
40 Profile* profile,
41 TabSpecificContentSettings* content_settings,
42 const content::MediaStreamRequest& request,
43 const content::MediaResponseCallback& callback)
44 : profile_(profile),
45 content_settings_(content_settings),
46 request_(request),
47 callback_(callback),
48 microphone_requested_(
49 request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE),
50 webcam_requested_(
51 request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE) {
52 // Don't call GetDevicePolicy from the initializer list since the
53 // implementation depends on member variables.
54 if (microphone_requested_ &&
55 GetDevicePolicy(prefs::kAudioCaptureAllowed) == ALWAYS_DENY) {
56 microphone_requested_ = false;
59 if (webcam_requested_ &&
60 GetDevicePolicy(prefs::kVideoCaptureAllowed) == ALWAYS_DENY) {
61 webcam_requested_ = false;
65 MediaStreamDevicesController::~MediaStreamDevicesController() {}
67 // static
68 void MediaStreamDevicesController::RegisterUserPrefs(
69 PrefRegistrySyncable* prefs) {
70 prefs->RegisterBooleanPref(prefs::kVideoCaptureAllowed,
71 true,
72 PrefRegistrySyncable::UNSYNCABLE_PREF);
73 prefs->RegisterBooleanPref(prefs::kAudioCaptureAllowed,
74 true,
75 PrefRegistrySyncable::UNSYNCABLE_PREF);
79 bool MediaStreamDevicesController::DismissInfoBarAndTakeActionOnSettings() {
80 // If this is a no UI check for policies only go straight to accept - policy
81 // check will be done automatically on the way.
82 if (request_.request_type == content::MEDIA_OPEN_DEVICE) {
83 Accept(false);
84 return true;
87 // Tab capture is allowed for extensions only and infobar is not shown for
88 // extensions.
89 if (request_.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE ||
90 request_.video_type == content::MEDIA_TAB_VIDEO_CAPTURE) {
91 Deny(false);
92 return true;
95 // Deny the request if the security origin is empty, this happens with
96 // file access without |--allow-file-access-from-files| flag.
97 if (request_.security_origin.is_empty()) {
98 Deny(false);
99 return true;
102 // Deny the request if there is no device attached to the OS.
103 if (!HasAnyAvailableDevice()) {
104 Deny(false);
105 return true;
108 // Check if any allow exception has been made for this request.
109 if (IsRequestAllowedByDefault()) {
110 Accept(false);
111 return true;
114 // Check if any block exception has been made for this request.
115 if (IsRequestBlockedByDefault()) {
116 Deny(false);
117 return true;
120 // Check if the media default setting is set to block.
121 if (IsDefaultMediaAccessBlocked()) {
122 Deny(false);
123 return true;
126 // Show the infobar.
127 return false;
130 const std::string& MediaStreamDevicesController::GetSecurityOriginSpec() const {
131 return request_.security_origin.spec();
134 void MediaStreamDevicesController::Accept(bool update_content_setting) {
135 if (content_settings_)
136 content_settings_->OnMediaStreamAllowed();
138 // Get the default devices for the request.
139 content::MediaStreamDevices devices;
140 if (microphone_requested_ || webcam_requested_) {
141 switch (request_.request_type) {
142 case content::MEDIA_OPEN_DEVICE:
143 // For open device request pick the desired device or fall back to the
144 // first available of the given type.
145 MediaCaptureDevicesDispatcher::GetInstance()->GetRequestedDevice(
146 request_.requested_device_id,
147 microphone_requested_,
148 webcam_requested_,
149 &devices);
150 break;
151 case content::MEDIA_DEVICE_ACCESS:
152 case content::MEDIA_GENERATE_STREAM:
153 case content::MEDIA_ENUMERATE_DEVICES:
154 // Get the default devices for the request.
155 MediaCaptureDevicesDispatcher::GetInstance()->
156 GetDefaultDevicesForProfile(profile_,
157 microphone_requested_,
158 webcam_requested_,
159 &devices);
160 break;
163 if (update_content_setting && IsSchemeSecure() && !devices.empty())
164 SetPermission(true);
167 callback_.Run(devices);
170 void MediaStreamDevicesController::Deny(bool update_content_setting) {
171 // TODO(markusheintz): Replace CONTENT_SETTINGS_TYPE_MEDIA_STREAM with the
172 // appropriate new CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC and
173 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
174 if (content_settings_) {
175 content_settings_->OnContentBlocked(CONTENT_SETTINGS_TYPE_MEDIASTREAM,
176 std::string());
179 if (update_content_setting)
180 SetPermission(false);
182 callback_.Run(content::MediaStreamDevices());
185 MediaStreamDevicesController::DevicePolicy
186 MediaStreamDevicesController::GetDevicePolicy(const char* policy_name) const {
187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
189 PrefService* prefs = profile_->GetPrefs();
190 if (!prefs->IsManagedPreference(policy_name))
191 return POLICY_NOT_SET;
193 return prefs->GetBoolean(policy_name) ? ALWAYS_ALLOW : ALWAYS_DENY;
196 bool MediaStreamDevicesController::IsRequestAllowedByDefault() const {
197 // The request from internal objects like chrome://URLs is always allowed.
198 if (ShouldAlwaysAllowOrigin())
199 return true;
201 struct {
202 bool has_capability;
203 const char* policy_name;
204 ContentSettingsType settings_type;
205 } device_checks[] = {
206 { microphone_requested_, prefs::kAudioCaptureAllowed,
207 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC },
208 { webcam_requested_, prefs::kVideoCaptureAllowed,
209 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA },
212 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(device_checks); ++i) {
213 if (!device_checks[i].has_capability)
214 continue;
216 DevicePolicy policy = GetDevicePolicy(device_checks[i].policy_name);
217 if (policy == ALWAYS_DENY ||
218 (policy == POLICY_NOT_SET &&
219 profile_->GetHostContentSettingsMap()->GetContentSetting(
220 request_.security_origin, request_.security_origin,
221 device_checks[i].settings_type, NO_RESOURCE_IDENTIFIER) !=
222 CONTENT_SETTING_ALLOW)) {
223 return false;
225 // If we get here, then either policy is set to ALWAYS_ALLOW or the content
226 // settings allow the request by default.
229 return true;
232 bool MediaStreamDevicesController::IsRequestBlockedByDefault() const {
233 if (microphone_requested_ &&
234 profile_->GetHostContentSettingsMap()->GetContentSetting(
235 request_.security_origin,
236 request_.security_origin,
237 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
238 NO_RESOURCE_IDENTIFIER) != CONTENT_SETTING_BLOCK) {
239 return false;
242 if (webcam_requested_ &&
243 profile_->GetHostContentSettingsMap()->GetContentSetting(
244 request_.security_origin,
245 request_.security_origin,
246 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
247 NO_RESOURCE_IDENTIFIER) != CONTENT_SETTING_BLOCK) {
248 return false;
251 return true;
254 bool MediaStreamDevicesController::IsDefaultMediaAccessBlocked() const {
255 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
256 // TODO(markusheintz): Replace CONTENT_SETTINGS_TYPE_MEDIA_STREAM with the
257 // appropriate new CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC and
258 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
259 ContentSetting current_setting =
260 profile_->GetHostContentSettingsMap()->GetDefaultContentSetting(
261 CONTENT_SETTINGS_TYPE_MEDIASTREAM, NULL);
262 return (current_setting == CONTENT_SETTING_BLOCK);
265 bool MediaStreamDevicesController::IsSchemeSecure() const {
266 return (request_.security_origin.SchemeIsSecure());
269 bool MediaStreamDevicesController::ShouldAlwaysAllowOrigin() const {
270 // TODO(markusheintz): Replace CONTENT_SETTINGS_TYPE_MEDIA_STREAM with the
271 // appropriate new CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC and
272 // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
273 return profile_->GetHostContentSettingsMap()->ShouldAllowAllContent(
274 request_.security_origin, request_.security_origin,
275 CONTENT_SETTINGS_TYPE_MEDIASTREAM);
278 void MediaStreamDevicesController::SetPermission(bool allowed) const {
279 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
280 #if defined(OS_ANDROID)
281 // We do not support sticky operations on Android yet.
282 return;
283 #endif
284 ContentSettingsPattern primary_pattern =
285 ContentSettingsPattern::FromURLNoWildcard(request_.security_origin);
286 // Check the pattern is valid or not. When the request is from a file access,
287 // no exception will be made.
288 if (!primary_pattern.IsValid())
289 return;
291 ContentSetting content_setting = allowed ?
292 CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
293 if (microphone_requested_) {
294 profile_->GetHostContentSettingsMap()->SetContentSetting(
295 primary_pattern,
296 ContentSettingsPattern::Wildcard(),
297 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
298 std::string(),
299 content_setting);
301 if (webcam_requested_) {
302 profile_->GetHostContentSettingsMap()->SetContentSetting(
303 primary_pattern,
304 ContentSettingsPattern::Wildcard(),
305 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
306 std::string(),
307 content_setting);