fix: getUserMedia
needs macOS system permissions check (#42899)
fix: getUserMedia needs macOS system permissions check Closes https://github.com/electron/electron/issues/42714 Closes https://github.com/electron/electron/issues/29861
This commit is contained in:
parent
c7709747d0
commit
fd907bc0a3
1 changed files with 94 additions and 65 deletions
|
@ -7,23 +7,29 @@
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include "components/content_settings/core/common/content_settings.h"
|
||||||
|
#include "components/webrtc/media_stream_devices_controller.h"
|
||||||
#include "content/public/browser/browser_context.h"
|
#include "content/public/browser/browser_context.h"
|
||||||
#include "content/public/browser/render_process_host.h"
|
#include "content/public/browser/render_process_host.h"
|
||||||
#include "content/public/browser/web_contents_user_data.h"
|
#include "content/public/browser/web_contents_user_data.h"
|
||||||
#include "shell/browser/electron_permission_manager.h"
|
#include "shell/browser/electron_permission_manager.h"
|
||||||
// #include "shell/browser/media/media_stream_devices_controller.h"
|
|
||||||
#include "components/content_settings/core/common/content_settings.h"
|
|
||||||
#include "components/webrtc/media_stream_devices_controller.h"
|
|
||||||
#include "shell/browser/media/media_capture_devices_dispatcher.h"
|
#include "shell/browser/media/media_capture_devices_dispatcher.h"
|
||||||
|
|
||||||
|
#if BUILDFLAG(IS_MAC)
|
||||||
|
#include "chrome/browser/media/webrtc/system_media_capture_permissions_mac.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using blink::mojom::MediaStreamRequestResult;
|
||||||
|
using blink::mojom::MediaStreamType;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr std::string_view MediaStreamTypeToString(
|
constexpr std::string_view MediaStreamTypeToString(
|
||||||
blink::mojom::MediaStreamType type) {
|
blink::mojom::MediaStreamType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE:
|
case MediaStreamType::DEVICE_AUDIO_CAPTURE:
|
||||||
return "audio";
|
return "audio";
|
||||||
case blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE:
|
case MediaStreamType::DEVICE_VIDEO_CAPTURE:
|
||||||
return "video";
|
return "video";
|
||||||
default:
|
default:
|
||||||
return "unknown";
|
return "unknown";
|
||||||
|
@ -48,53 +54,74 @@ namespace {
|
||||||
-1 /* kFullDesktopScreenId */);
|
-1 /* kFullDesktopScreenId */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if BUILDFLAG(IS_MAC)
|
||||||
|
bool SystemMediaPermissionDenied(const content::MediaStreamRequest& request) {
|
||||||
|
if (request.audio_type != MediaStreamType::NO_SERVICE) {
|
||||||
|
const auto system_audio_permission =
|
||||||
|
system_media_permissions::CheckSystemAudioCapturePermission();
|
||||||
|
return system_audio_permission ==
|
||||||
|
system_media_permissions::SystemPermission::kRestricted ||
|
||||||
|
system_audio_permission ==
|
||||||
|
system_media_permissions::SystemPermission::kDenied;
|
||||||
|
}
|
||||||
|
if (request.video_type != MediaStreamType::NO_SERVICE) {
|
||||||
|
const auto system_video_permission =
|
||||||
|
system_media_permissions::CheckSystemVideoCapturePermission();
|
||||||
|
return system_video_permission ==
|
||||||
|
system_media_permissions::SystemPermission::kRestricted ||
|
||||||
|
system_video_permission ==
|
||||||
|
system_media_permissions::SystemPermission::kDenied;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Handles requests for legacy-style `navigator.getUserMedia(...)` calls.
|
// Handles requests for legacy-style `navigator.getUserMedia(...)` calls.
|
||||||
// This includes desktop capture through the chromeMediaSource /
|
// This includes desktop capture through the chromeMediaSource /
|
||||||
// chromeMediaSourceId constraints.
|
// chromeMediaSourceId constraints.
|
||||||
void HandleUserMediaRequest(const content::MediaStreamRequest& request,
|
void HandleUserMediaRequest(const content::MediaStreamRequest& request,
|
||||||
content::MediaResponseCallback callback) {
|
content::MediaResponseCallback callback) {
|
||||||
blink::mojom::StreamDevicesSetPtr stream_devices_set =
|
auto stream_devices_set = blink::mojom::StreamDevicesSet::New();
|
||||||
blink::mojom::StreamDevicesSet::New();
|
auto devices = blink::mojom::StreamDevices::New();
|
||||||
stream_devices_set->stream_devices.emplace_back(
|
stream_devices_set->stream_devices.emplace_back(std::move(devices));
|
||||||
blink::mojom::StreamDevices::New());
|
auto& devices_ref = *stream_devices_set->stream_devices[0];
|
||||||
blink::mojom::StreamDevices& devices = *stream_devices_set->stream_devices[0];
|
|
||||||
|
|
||||||
if (request.audio_type ==
|
if (request.audio_type == MediaStreamType::GUM_TAB_AUDIO_CAPTURE ||
|
||||||
blink::mojom::MediaStreamType::GUM_TAB_AUDIO_CAPTURE) {
|
request.audio_type == MediaStreamType::GUM_DESKTOP_AUDIO_CAPTURE) {
|
||||||
devices.audio_device = blink::MediaStreamDevice(
|
devices_ref.audio_device = blink::MediaStreamDevice(
|
||||||
blink::mojom::MediaStreamType::GUM_TAB_AUDIO_CAPTURE, "", "");
|
request.audio_type,
|
||||||
}
|
request.audio_type == MediaStreamType::GUM_DESKTOP_AUDIO_CAPTURE
|
||||||
if (request.video_type ==
|
? "loopback"
|
||||||
blink::mojom::MediaStreamType::GUM_TAB_VIDEO_CAPTURE) {
|
: "",
|
||||||
devices.video_device = blink::MediaStreamDevice(
|
request.audio_type == MediaStreamType::GUM_DESKTOP_AUDIO_CAPTURE
|
||||||
blink::mojom::MediaStreamType::GUM_TAB_VIDEO_CAPTURE, "", "");
|
? "System Audio"
|
||||||
}
|
: "");
|
||||||
if (request.audio_type ==
|
|
||||||
blink::mojom::MediaStreamType::GUM_DESKTOP_AUDIO_CAPTURE) {
|
|
||||||
devices.audio_device = blink::MediaStreamDevice(
|
|
||||||
blink::mojom::MediaStreamType::GUM_DESKTOP_AUDIO_CAPTURE, "loopback",
|
|
||||||
"System Audio");
|
|
||||||
}
|
|
||||||
if (request.video_type ==
|
|
||||||
blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE) {
|
|
||||||
devices.video_device = blink::MediaStreamDevice(
|
|
||||||
blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE,
|
|
||||||
GetScreenId(request.requested_video_device_ids).ToString(), "Screen");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool empty =
|
if (request.video_type == MediaStreamType::GUM_TAB_VIDEO_CAPTURE ||
|
||||||
!devices.audio_device.has_value() && !devices.video_device.has_value();
|
request.video_type == MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE) {
|
||||||
std::move(callback).Run(
|
devices_ref.video_device = blink::MediaStreamDevice(
|
||||||
*stream_devices_set,
|
request.video_type,
|
||||||
empty ? blink::mojom::MediaStreamRequestResult::NO_HARDWARE
|
request.video_type == MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE
|
||||||
: blink::mojom::MediaStreamRequestResult::OK,
|
? GetScreenId(request.requested_video_device_ids).ToString()
|
||||||
|
: "",
|
||||||
|
request.video_type == MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE
|
||||||
|
? "Screen"
|
||||||
|
: "");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty = !devices_ref.audio_device.has_value() &&
|
||||||
|
!devices_ref.video_device.has_value();
|
||||||
|
std::move(callback).Run(*stream_devices_set,
|
||||||
|
empty ? MediaStreamRequestResult::NO_HARDWARE
|
||||||
|
: MediaStreamRequestResult::OK,
|
||||||
nullptr);
|
nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnMediaStreamRequestResponse(
|
void OnMediaStreamRequestResponse(
|
||||||
content::MediaResponseCallback callback,
|
content::MediaResponseCallback callback,
|
||||||
const blink::mojom::StreamDevicesSet& stream_devices_set,
|
const blink::mojom::StreamDevicesSet& stream_devices_set,
|
||||||
blink::mojom::MediaStreamRequestResult result,
|
MediaStreamRequestResult result,
|
||||||
bool blocked_by_permissions_policy,
|
bool blocked_by_permissions_policy,
|
||||||
ContentSetting audio_setting,
|
ContentSetting audio_setting,
|
||||||
ContentSetting video_setting) {
|
ContentSetting video_setting) {
|
||||||
|
@ -105,31 +132,34 @@ void MediaAccessAllowed(const content::MediaStreamRequest& request,
|
||||||
content::MediaResponseCallback callback,
|
content::MediaResponseCallback callback,
|
||||||
bool allowed) {
|
bool allowed) {
|
||||||
if (allowed) {
|
if (allowed) {
|
||||||
if (request.video_type ==
|
#if BUILDFLAG(IS_MAC)
|
||||||
blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE ||
|
// If the request was approved, ask for system permissions if needed.
|
||||||
request.audio_type ==
|
// See
|
||||||
blink::mojom::MediaStreamType::GUM_DESKTOP_AUDIO_CAPTURE ||
|
// chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc.
|
||||||
request.video_type ==
|
if (SystemMediaPermissionDenied(request)) {
|
||||||
blink::mojom::MediaStreamType::GUM_TAB_VIDEO_CAPTURE ||
|
std::move(callback).Run(blink::mojom::StreamDevicesSet(),
|
||||||
request.audio_type ==
|
MediaStreamRequestResult::PERMISSION_DENIED,
|
||||||
blink::mojom::MediaStreamType::GUM_TAB_AUDIO_CAPTURE) {
|
nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (request.video_type == MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE ||
|
||||||
|
request.audio_type == MediaStreamType::GUM_DESKTOP_AUDIO_CAPTURE ||
|
||||||
|
request.video_type == MediaStreamType::GUM_TAB_VIDEO_CAPTURE ||
|
||||||
|
request.audio_type == MediaStreamType::GUM_TAB_AUDIO_CAPTURE) {
|
||||||
HandleUserMediaRequest(request, std::move(callback));
|
HandleUserMediaRequest(request, std::move(callback));
|
||||||
} else if (request.video_type ==
|
} else if (request.video_type == MediaStreamType::DEVICE_VIDEO_CAPTURE ||
|
||||||
blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE ||
|
request.audio_type == MediaStreamType::DEVICE_AUDIO_CAPTURE) {
|
||||||
request.audio_type ==
|
|
||||||
blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) {
|
|
||||||
webrtc::MediaStreamDevicesController::RequestPermissions(
|
webrtc::MediaStreamDevicesController::RequestPermissions(
|
||||||
request, MediaCaptureDevicesDispatcher::GetInstance(),
|
request, MediaCaptureDevicesDispatcher::GetInstance(),
|
||||||
base::BindOnce(&OnMediaStreamRequestResponse, std::move(callback)),
|
base::BindOnce(&OnMediaStreamRequestResponse, std::move(callback)),
|
||||||
allowed);
|
allowed);
|
||||||
} else if (request.video_type ==
|
} else if (request.video_type == MediaStreamType::DISPLAY_VIDEO_CAPTURE ||
|
||||||
blink::mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE ||
|
|
||||||
request.video_type == blink::mojom::MediaStreamType::
|
|
||||||
DISPLAY_VIDEO_CAPTURE_THIS_TAB ||
|
|
||||||
request.video_type ==
|
request.video_type ==
|
||||||
blink::mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE_SET ||
|
MediaStreamType::DISPLAY_VIDEO_CAPTURE_THIS_TAB ||
|
||||||
request.audio_type ==
|
request.video_type ==
|
||||||
blink::mojom::MediaStreamType::DISPLAY_AUDIO_CAPTURE) {
|
MediaStreamType::DISPLAY_VIDEO_CAPTURE_SET ||
|
||||||
|
request.audio_type == MediaStreamType::DISPLAY_AUDIO_CAPTURE) {
|
||||||
content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
|
content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
|
||||||
request.render_process_id, request.render_frame_id);
|
request.render_process_id, request.render_frame_id);
|
||||||
if (!rfh)
|
if (!rfh)
|
||||||
|
@ -144,16 +174,15 @@ void MediaAccessAllowed(const content::MediaStreamRequest& request,
|
||||||
return;
|
return;
|
||||||
std::move(split_callback.first)
|
std::move(split_callback.first)
|
||||||
.Run(blink::mojom::StreamDevicesSet(),
|
.Run(blink::mojom::StreamDevicesSet(),
|
||||||
blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, nullptr);
|
MediaStreamRequestResult::NOT_SUPPORTED, nullptr);
|
||||||
} else {
|
} else {
|
||||||
std::move(callback).Run(
|
std::move(callback).Run(blink::mojom::StreamDevicesSet(),
|
||||||
blink::mojom::StreamDevicesSet(),
|
MediaStreamRequestResult::NOT_SUPPORTED, nullptr);
|
||||||
blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, nullptr);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std::move(callback).Run(
|
std::move(callback).Run(blink::mojom::StreamDevicesSet(),
|
||||||
blink::mojom::StreamDevicesSet(),
|
MediaStreamRequestResult::PERMISSION_DENIED,
|
||||||
blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, nullptr);
|
nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue