| // 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; | 
 | } |