media_capture_util.cc 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // Copyright 2014 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.
  4. #include "extensions/browser/media_capture_util.h"
  5. #include <algorithm>
  6. #include <string>
  7. #include <utility>
  8. #include "base/callback.h"
  9. #include "base/check.h"
  10. #include "content/public/browser/media_capture_devices.h"
  11. #include "extensions/common/extension.h"
  12. #include "extensions/common/permissions/permissions_data.h"
  13. #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h"
  14. #include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
  15. using blink::MediaStreamDevice;
  16. using blink::MediaStreamDevices;
  17. using content::MediaCaptureDevices;
  18. using content::MediaStreamUI;
  19. using extensions::mojom::APIPermissionID;
  20. namespace extensions {
  21. namespace {
  22. const MediaStreamDevice* GetRequestedDeviceOrDefault(
  23. const MediaStreamDevices& devices,
  24. const std::string& requested_device_id) {
  25. if (!requested_device_id.empty()) {
  26. auto it =
  27. std::find_if(devices.begin(), devices.end(),
  28. [requested_device_id](const MediaStreamDevice& device) {
  29. return device.id == requested_device_id;
  30. });
  31. return it != devices.end() ? &(*it) : nullptr;
  32. }
  33. if (!devices.empty())
  34. return &devices[0];
  35. return nullptr;
  36. }
  37. } // namespace
  38. namespace media_capture_util {
  39. // See also Chrome's MediaCaptureDevicesDispatcher.
  40. void GrantMediaStreamRequest(content::WebContents* web_contents,
  41. const content::MediaStreamRequest& request,
  42. content::MediaResponseCallback callback,
  43. const Extension* extension) {
  44. // app_shell only supports audio and video capture, not tab or screen capture.
  45. DCHECK(request.audio_type ==
  46. blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE ||
  47. request.video_type ==
  48. blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE);
  49. // TOOD(crbug.com/1300883): Generalize to multiple streams.
  50. blink::mojom::StreamDevicesSet stream_devices_set;
  51. stream_devices_set.stream_devices.emplace_back(
  52. blink::mojom::StreamDevices::New());
  53. blink::mojom::StreamDevices& devices = *stream_devices_set.stream_devices[0];
  54. if (request.audio_type ==
  55. blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) {
  56. VerifyMediaAccessPermission(request.audio_type, extension);
  57. const MediaStreamDevice* device = GetRequestedDeviceOrDefault(
  58. MediaCaptureDevices::GetInstance()->GetAudioCaptureDevices(),
  59. request.requested_audio_device_id);
  60. if (device)
  61. devices.audio_device = *device;
  62. }
  63. if (request.video_type ==
  64. blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE) {
  65. VerifyMediaAccessPermission(request.video_type, extension);
  66. const MediaStreamDevice* device = GetRequestedDeviceOrDefault(
  67. MediaCaptureDevices::GetInstance()->GetVideoCaptureDevices(),
  68. request.requested_video_device_id);
  69. if (device)
  70. devices.video_device = *device;
  71. }
  72. // TODO(jamescook): Should we show a recording icon somewhere? If so, where?
  73. std::unique_ptr<MediaStreamUI> ui;
  74. std::move(callback).Run(
  75. stream_devices_set,
  76. (devices.audio_device.has_value() || devices.video_device.has_value())
  77. ? blink::mojom::MediaStreamRequestResult::OK
  78. : blink::mojom::MediaStreamRequestResult::INVALID_STATE,
  79. std::move(ui));
  80. }
  81. void VerifyMediaAccessPermission(blink::mojom::MediaStreamType type,
  82. const Extension* extension) {
  83. const PermissionsData* permissions_data = extension->permissions_data();
  84. if (type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) {
  85. // app_shell has no UI surface to show an error, and on an embedded device
  86. // it's better to crash than to have a feature not work.
  87. CHECK(permissions_data->HasAPIPermission(APIPermissionID::kAudioCapture))
  88. << "Audio capture request but no audioCapture permission in manifest.";
  89. } else {
  90. DCHECK(type == blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE);
  91. CHECK(permissions_data->HasAPIPermission(APIPermissionID::kVideoCapture))
  92. << "Video capture request but no videoCapture permission in manifest.";
  93. }
  94. }
  95. bool CheckMediaAccessPermission(blink::mojom::MediaStreamType type,
  96. const Extension* extension) {
  97. const PermissionsData* permissions_data = extension->permissions_data();
  98. if (type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) {
  99. return permissions_data->HasAPIPermission(APIPermissionID::kAudioCapture);
  100. }
  101. DCHECK(type == blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE);
  102. return permissions_data->HasAPIPermission(APIPermissionID::kVideoCapture);
  103. }
  104. } // namespace media_capture_util
  105. } // namespace extensions