1 // Copyright 2015 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_permission.h"
7 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
8 #include "chrome/browser/media/media_stream_device_permission_context.h"
9 #include "chrome/browser/media/media_stream_device_permissions.h"
10 #include "chrome/browser/permissions/permission_context.h"
11 #include "chrome/browser/permissions/permission_context_base.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/common/pref_names.h"
14 #include "content/public/browser/permission_manager.h"
15 #include "content/public/browser/permission_type.h"
16 #include "content/public/common/url_constants.h"
17 #include "extensions/common/constants.h"
21 content::PermissionType
ContentSettingsTypeToPermission(
22 ContentSettingsType content_setting
) {
23 if (content_setting
== CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
) {
24 return content::PermissionType::AUDIO_CAPTURE
;
26 DCHECK_EQ(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
, content_setting
);
27 return content::PermissionType::VIDEO_CAPTURE
;
33 MediaPermission::MediaPermission(ContentSettingsType content_type
,
34 content::MediaStreamRequestType request_type
,
35 const GURL
& requesting_origin
,
36 const GURL
& embedding_origin
,
38 : content_type_(content_type
),
39 request_type_(request_type
),
40 requesting_origin_(requesting_origin
),
41 embedding_origin_(embedding_origin
),
44 ContentSetting
MediaPermission::GetPermissionStatus(
45 content::MediaStreamRequestResult
* denial_reason
) const {
46 // Deny the request if the security origin is empty, this happens with
47 // file access without |--allow-file-access-from-files| flag.
48 if (requesting_origin_
.is_empty()) {
49 *denial_reason
= content::MEDIA_DEVICE_INVALID_SECURITY_ORIGIN
;
50 return CONTENT_SETTING_BLOCK
;
53 // Check policy and content settings.
54 ContentSetting result
= GetStoredContentSetting();
55 if (result
== CONTENT_SETTING_BLOCK
)
56 *denial_reason
= content::MEDIA_DEVICE_PERMISSION_DENIED
;
61 ContentSetting
MediaPermission::GetPermissionStatusWithDeviceRequired(
62 const std::string
& device_id
,
63 content::MediaStreamRequestResult
* denial_reason
) const {
64 // Deny the request if there is no device attached to the OS of the requested
66 if (!HasAvailableDevices(device_id
)) {
67 *denial_reason
= content::MEDIA_DEVICE_NO_HARDWARE
;
68 return CONTENT_SETTING_BLOCK
;
71 return GetPermissionStatus(denial_reason
);
74 ContentSetting
MediaPermission::GetStoredContentSetting() const {
75 content::PermissionType permission_type
=
76 ContentSettingsTypeToPermission(content_type_
);
77 PermissionContextBase
* permission_context
=
78 PermissionContext::Get(profile_
, permission_type
);
80 if (!permission_context
)
81 return CONTENT_SETTING_BLOCK
;
83 MediaStreamDevicePermissionContext
* media_device_permission_context
=
84 static_cast<MediaStreamDevicePermissionContext
*>(permission_context
);
86 if (request_type_
== content::MEDIA_OPEN_DEVICE
) {
87 return media_device_permission_context
->GetPermissionStatusForPepper(
88 requesting_origin_
, embedding_origin_
);
90 return media_device_permission_context
->GetPermissionStatus(
91 requesting_origin_
, embedding_origin_
);
95 bool MediaPermission::HasAvailableDevices(const std::string
& device_id
) const {
96 const content::MediaStreamDevices
* devices
= nullptr;
97 if (content_type_
== CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
) {
99 &MediaCaptureDevicesDispatcher::GetInstance()->GetAudioCaptureDevices();
100 } else if (content_type_
== CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
) {
102 &MediaCaptureDevicesDispatcher::GetInstance()->GetVideoCaptureDevices();
107 // TODO(tommi): It's kind of strange to have this here since if we fail this
108 // test, there'll be a UI shown that indicates to the user that access to
109 // non-existing audio/video devices has been denied. The user won't have
110 // any way to change that but there will be a UI shown which indicates that
111 // access is blocked.
112 if (devices
->empty())
115 // Note: we check device_id before dereferencing devices. If the requested
116 // device id is non-empty, then the corresponding device list must not be
118 if (!device_id
.empty() && !devices
->FindById(device_id
))