|  | // Copyright 2014 The Chromium Authors | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "android_webview/browser/permission/media_access_permission_request.h" | 
|  |  | 
|  | #include <algorithm> | 
|  | #include <utility> | 
|  |  | 
|  | #include "android_webview/browser/aw_browser_context.h" | 
|  | #include "android_webview/browser/permission/aw_permission_request.h" | 
|  | #include "android_webview/common/aw_features.h" | 
|  | #include "content/public/browser/media_capture_devices.h" | 
|  | #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h" | 
|  | #include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" | 
|  |  | 
|  | using blink::MediaStreamDevice; | 
|  | using blink::MediaStreamDevices; | 
|  | using content::MediaCaptureDevices; | 
|  |  | 
|  | namespace android_webview { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | // Return the device specified by |device_id| if exists, otherwise the first | 
|  | // available device is returned. | 
|  | const MediaStreamDevice* GetDeviceByIdOrFirstAvailable( | 
|  | const MediaStreamDevices& devices, | 
|  | const std::vector<std::string>& device_ids) { | 
|  | if (devices.empty()) | 
|  | return nullptr; | 
|  |  | 
|  | if (!device_ids.empty()) { | 
|  | for (const auto& device : devices) { | 
|  | if (device.id == device_ids.front()) { | 
|  | return &device; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | return &devices.front(); | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | MediaAccessPermissionRequest::MediaAccessPermissionRequest( | 
|  | const content::MediaStreamRequest& request, | 
|  | content::MediaResponseCallback callback, | 
|  | AwPermissionManager& permission_manager, | 
|  | bool can_cache_file_url_permissions) | 
|  | : request_(request), | 
|  | callback_(std::move(callback)), | 
|  | permission_manager_(permission_manager), | 
|  | can_cache_file_url_permissions_(can_cache_file_url_permissions) {} | 
|  |  | 
|  | MediaAccessPermissionRequest::~MediaAccessPermissionRequest() {} | 
|  |  | 
|  | void MediaAccessPermissionRequest::NotifyRequestResult(bool allowed) { | 
|  | std::unique_ptr<content::MediaStreamUI> ui; | 
|  | if (!allowed) { | 
|  | permission_manager_->ClearEnumerateDevicesCachedPermission( | 
|  | request_.url_origin, | 
|  | /* remove_audio */ request_.audio_type == | 
|  | blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE, | 
|  | /* remove_video */ request_.video_type == | 
|  | blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); | 
|  | std::move(callback_).Run( | 
|  | blink::mojom::StreamDevicesSet(), | 
|  | blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, | 
|  | std::move(ui)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | blink::mojom::StreamDevicesSet stream_devices_set; | 
|  | stream_devices_set.stream_devices.emplace_back( | 
|  | blink::mojom::StreamDevices::New()); | 
|  | blink::mojom::StreamDevices& devices = *stream_devices_set.stream_devices[0]; | 
|  | if (request_.audio_type == | 
|  | blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) { | 
|  | const MediaStreamDevices& audio_devices = | 
|  | audio_test_devices_.empty() | 
|  | ? MediaCaptureDevices::GetInstance()->GetAudioCaptureDevices() | 
|  | : audio_test_devices_; | 
|  | const MediaStreamDevice* device = GetDeviceByIdOrFirstAvailable( | 
|  | audio_devices, request_.requested_audio_device_ids); | 
|  | if (device) | 
|  | devices.audio_device = *device; | 
|  | if (request_.url_origin.scheme() != url::kFileScheme || | 
|  | can_cache_file_url_permissions_) { | 
|  | permission_manager_->SetOriginCanReadEnumerateDevicesAudioLabels( | 
|  | request_.url_origin, true); | 
|  | } | 
|  | } | 
|  |  | 
|  | if (request_.video_type == | 
|  | blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE) { | 
|  | const MediaStreamDevices& video_devices = | 
|  | video_test_devices_.empty() | 
|  | ? MediaCaptureDevices::GetInstance()->GetVideoCaptureDevices() | 
|  | : video_test_devices_; | 
|  | const MediaStreamDevice* device = GetDeviceByIdOrFirstAvailable( | 
|  | video_devices, request_.requested_video_device_ids); | 
|  | if (device) | 
|  | devices.video_device = *device; | 
|  | if (request_.url_origin.scheme() != url::kFileScheme || | 
|  | can_cache_file_url_permissions_) { | 
|  | permission_manager_->SetOriginCanReadEnumerateDevicesVideoLabels( | 
|  | request_.url_origin, true); | 
|  | } | 
|  | } | 
|  |  | 
|  | const bool has_no_hardware = | 
|  | !devices.audio_device.has_value() && !devices.video_device.has_value(); | 
|  | if (has_no_hardware) { | 
|  | stream_devices_set.stream_devices.clear(); | 
|  | } | 
|  | std::move(callback_).Run( | 
|  | stream_devices_set, | 
|  | has_no_hardware ? blink::mojom::MediaStreamRequestResult::NO_HARDWARE | 
|  | : blink::mojom::MediaStreamRequestResult::OK, | 
|  | std::move(ui)); | 
|  | } | 
|  |  | 
|  | const GURL& MediaAccessPermissionRequest::GetOrigin() { | 
|  | return request_.security_origin; | 
|  | } | 
|  |  | 
|  | int64_t MediaAccessPermissionRequest::GetResources() { | 
|  | return (request_.audio_type == | 
|  | blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE | 
|  | ? AwPermissionRequest::AudioCapture | 
|  | : 0) | | 
|  | (request_.video_type == | 
|  | blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE | 
|  | ? AwPermissionRequest::VideoCapture | 
|  | : 0); | 
|  | } | 
|  |  | 
|  | }  // namespace android_webview |