| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/media/media_permission.h" |
| |
| #include "chrome/browser/media/media_capture_devices_dispatcher.h" |
| #include "chrome/browser/media/media_stream_device_permission_context.h" |
| #include "chrome/browser/media/media_stream_device_permissions.h" |
| #include "chrome/browser/permissions/permission_context.h" |
| #include "chrome/browser/permissions/permission_context_base.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/common/pref_names.h" |
| #include "content/public/browser/permission_manager.h" |
| #include "content/public/browser/permission_type.h" |
| #include "content/public/common/url_constants.h" |
| #include "extensions/common/constants.h" |
| |
| namespace { |
| |
| content::PermissionType ContentSettingsTypeToPermission( |
| ContentSettingsType content_setting) { |
| if (content_setting == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC) { |
| return content::PermissionType::AUDIO_CAPTURE; |
| } else { |
| DCHECK_EQ(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, content_setting); |
| return content::PermissionType::VIDEO_CAPTURE; |
| } |
| } |
| |
| } // namespace |
| |
| MediaPermission::MediaPermission(ContentSettingsType content_type, |
| bool is_insecure_pepper_request, |
| const GURL& requesting_origin, |
| const GURL& embedding_origin, |
| Profile* profile) |
| : content_type_(content_type), |
| is_insecure_pepper_request_(is_insecure_pepper_request), |
| requesting_origin_(requesting_origin), |
| embedding_origin_(embedding_origin), |
| profile_(profile) {} |
| |
| ContentSetting MediaPermission::GetPermissionStatus( |
| content::MediaStreamRequestResult* denial_reason) const { |
| // Deny the request if the security origin is empty, this happens with |
| // file access without |--allow-file-access-from-files| flag. |
| if (requesting_origin_.is_empty()) { |
| *denial_reason = content::MEDIA_DEVICE_INVALID_SECURITY_ORIGIN; |
| return CONTENT_SETTING_BLOCK; |
| } |
| |
| // Use the Permission Context to find out if the kill switch is on. Set the |
| // denial reason to kill switch. |
| content::PermissionType permission_type = |
| ContentSettingsTypeToPermission(content_type_); |
| PermissionContextBase* permission_context = |
| PermissionContext::Get(profile_, permission_type); |
| |
| if (!permission_context) { |
| *denial_reason = content::MEDIA_DEVICE_PERMISSION_DENIED; |
| return CONTENT_SETTING_BLOCK; |
| } |
| |
| MediaStreamDevicePermissionContext* media_device_permission_context = |
| static_cast<MediaStreamDevicePermissionContext*>(permission_context); |
| |
| if (media_device_permission_context->IsPermissionKillSwitchOn()) { |
| *denial_reason = content::MEDIA_DEVICE_KILL_SWITCH_ON; |
| return CONTENT_SETTING_BLOCK; |
| } |
| |
| // Check policy and content settings. |
| ContentSetting result = |
| GetStoredContentSetting(media_device_permission_context); |
| if (result == CONTENT_SETTING_BLOCK) |
| *denial_reason = content::MEDIA_DEVICE_PERMISSION_DENIED; |
| |
| return result; |
| } |
| |
| ContentSetting MediaPermission::GetPermissionStatusWithDeviceRequired( |
| const std::string& device_id, |
| content::MediaStreamRequestResult* denial_reason) const { |
| // Deny the request if there is no device attached to the OS of the requested |
| // type. |
| if (!HasAvailableDevices(device_id)) { |
| *denial_reason = content::MEDIA_DEVICE_NO_HARDWARE; |
| return CONTENT_SETTING_BLOCK; |
| } |
| |
| return GetPermissionStatus(denial_reason); |
| } |
| |
| ContentSetting MediaPermission::GetStoredContentSetting( |
| MediaStreamDevicePermissionContext* media_device_permission_context) const { |
| if (is_insecure_pepper_request_) { |
| return media_device_permission_context |
| ->GetPermissionStatusAllowingInsecureForPepper(requesting_origin_, |
| embedding_origin_); |
| } else { |
| return media_device_permission_context->GetPermissionStatus( |
| requesting_origin_, embedding_origin_); |
| } |
| } |
| |
| bool MediaPermission::HasAvailableDevices(const std::string& device_id) const { |
| const content::MediaStreamDevices* devices = nullptr; |
| if (content_type_ == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC) { |
| devices = |
| &MediaCaptureDevicesDispatcher::GetInstance()->GetAudioCaptureDevices(); |
| } else if (content_type_ == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA) { |
| devices = |
| &MediaCaptureDevicesDispatcher::GetInstance()->GetVideoCaptureDevices(); |
| } else { |
| NOTREACHED(); |
| } |
| |
| // TODO(tommi): It's kind of strange to have this here since if we fail this |
| // test, there'll be a UI shown that indicates to the user that access to |
| // non-existing audio/video devices has been denied. The user won't have |
| // any way to change that but there will be a UI shown which indicates that |
| // access is blocked. |
| if (devices->empty()) |
| return false; |
| |
| // Note: we check device_id before dereferencing devices. If the requested |
| // device id is non-empty, then the corresponding device list must not be |
| // NULL. |
| if (!device_id.empty() && !devices->FindById(device_id)) |
| return false; |
| |
| return true; |
| } |