Skip to content

Commit 39bc7c8

Browse files
trop[bot]miniak
andauthored
feat: implement systemPreferences.getMediaAccessStatus() on Windows (electron#24311)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
1 parent 991d982 commit 39bc7c8

File tree

5 files changed

+75
-6
lines changed

5 files changed

+75
-6
lines changed

docs/api/system-preferences.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ This API itself will not protect your user data; rather, it is a mechanism to al
416416

417417
Returns `Boolean` - `true` if the current process is a trusted accessibility client and `false` if it is not.
418418

419-
### `systemPreferences.getMediaAccessStatus(mediaType)` _macOS_
419+
### `systemPreferences.getMediaAccessStatus(mediaType)` _Windows_ _macOS_
420420

421421
* `mediaType` String - Can be `microphone`, `camera` or `screen`.
422422

@@ -426,6 +426,9 @@ This user consent was not required on macOS 10.13 High Sierra or lower so this m
426426
macOS 10.14 Mojave or higher requires consent for `microphone` and `camera` access.
427427
macOS 10.15 Catalina or higher requires consent for `screen` access.
428428

429+
Windows 10 has a global setting controlling `microphone` and `camera` access for all win32 applications.
430+
It will always return `granted` for `screen` and for all media types on older versions of Windows.
431+
429432
### `systemPreferences.askForMediaAccess(mediaType)` _macOS_
430433

431434
* `mediaType` String - the type of media being requested; can be `microphone`, `camera`.

shell/browser/api/electron_api_system_preferences.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ void SystemPreferences::BuildPrototype(
7373
#if defined(OS_WIN) || defined(OS_MACOSX)
7474
.SetMethod("getColor", &SystemPreferences::GetColor)
7575
.SetMethod("getAccentColor", &SystemPreferences::GetAccentColor)
76+
.SetMethod("getMediaAccessStatus",
77+
&SystemPreferences::GetMediaAccessStatus)
7678
#endif
7779

7880
#if defined(OS_WIN)
@@ -112,8 +114,6 @@ void SystemPreferences::BuildPrototype(
112114
.SetMethod("promptTouchID", &SystemPreferences::PromptTouchID)
113115
.SetMethod("isTrustedAccessibilityClient",
114116
&SystemPreferences::IsTrustedAccessibilityClient)
115-
.SetMethod("getMediaAccessStatus",
116-
&SystemPreferences::GetMediaAccessStatus)
117117
.SetMethod("askForMediaAccess", &SystemPreferences::AskForMediaAccess)
118118
#endif
119119
.SetMethod("isInvertedColorScheme",

shell/browser/api/electron_api_system_preferences.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ class SystemPreferences : public gin_helper::EventEmitter<SystemPreferences>
4949
std::string GetAccentColor();
5050
std::string GetColor(gin_helper::ErrorThrower thrower,
5151
const std::string& color);
52+
std::string GetMediaAccessStatus(const std::string& media_type,
53+
gin_helper::Arguments* args);
5254
#endif
5355
#if defined(OS_WIN)
5456
bool IsAeroGlassEnabled();
@@ -99,8 +101,6 @@ class SystemPreferences : public gin_helper::EventEmitter<SystemPreferences>
99101

100102
static bool IsTrustedAccessibilityClient(bool prompt);
101103

102-
std::string GetMediaAccessStatus(const std::string& media_type,
103-
gin_helper::Arguments* args);
104104
v8::Local<v8::Promise> AskForMediaAccess(v8::Isolate* isolate,
105105
const std::string& media_type);
106106

shell/browser/api/electron_api_system_preferences_win.cc

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
// found in the LICENSE file.
44

55
#include <dwmapi.h>
6+
#include <windows.devices.enumeration.h>
7+
#include <wrl/client.h>
68
#include <iomanip>
79

810
#include "shell/browser/api/electron_api_system_preferences.h"
911

12+
#include "base/win/core_winrt_util.h"
1013
#include "base/win/wrapped_window_proc.h"
1114
#include "shell/common/color_util.h"
1215
#include "ui/base/win/shell.h"
@@ -20,6 +23,51 @@ namespace {
2023
const wchar_t kSystemPreferencesWindowClass[] =
2124
L"Electron_SystemPreferencesHostWindow";
2225

26+
using ABI::Windows::Devices::Enumeration::DeviceAccessStatus;
27+
using ABI::Windows::Devices::Enumeration::DeviceClass;
28+
using ABI::Windows::Devices::Enumeration::IDeviceAccessInformation;
29+
using ABI::Windows::Devices::Enumeration::IDeviceAccessInformationStatics;
30+
using Microsoft::WRL::ComPtr;
31+
32+
DeviceAccessStatus GetDeviceAccessStatus(DeviceClass device_class) {
33+
ComPtr<IDeviceAccessInformationStatics> dev_access_info_statics;
34+
HRESULT hr = base::win::GetActivationFactory<
35+
IDeviceAccessInformationStatics,
36+
RuntimeClass_Windows_Devices_Enumeration_DeviceAccessInformation>(
37+
&dev_access_info_statics);
38+
if (FAILED(hr)) {
39+
VLOG(1) << "IDeviceAccessInformationStatics failed: " << hr;
40+
return DeviceAccessStatus::DeviceAccessStatus_Allowed;
41+
}
42+
43+
ComPtr<IDeviceAccessInformation> dev_access_info;
44+
hr = dev_access_info_statics->CreateFromDeviceClass(device_class,
45+
&dev_access_info);
46+
if (FAILED(hr)) {
47+
VLOG(1) << "IDeviceAccessInformation failed: " << hr;
48+
return DeviceAccessStatus::DeviceAccessStatus_Allowed;
49+
}
50+
51+
auto status = DeviceAccessStatus::DeviceAccessStatus_Unspecified;
52+
dev_access_info->get_CurrentStatus(&status);
53+
return status;
54+
}
55+
56+
std::string ConvertDeviceAccessStatus(DeviceAccessStatus value) {
57+
switch (value) {
58+
case DeviceAccessStatus::DeviceAccessStatus_Unspecified:
59+
return "not-determined";
60+
case DeviceAccessStatus::DeviceAccessStatus_Allowed:
61+
return "granted";
62+
case DeviceAccessStatus::DeviceAccessStatus_DeniedBySystem:
63+
return "restricted";
64+
case DeviceAccessStatus::DeviceAccessStatus_DeniedByUser:
65+
return "denied";
66+
default:
67+
return "unknown";
68+
}
69+
}
70+
2371
} // namespace
2472

2573
namespace api {
@@ -117,6 +165,24 @@ std::string SystemPreferences::GetColor(gin_helper::ErrorThrower thrower,
117165
return ToRGBHex(color_utils::GetSysSkColor(id));
118166
}
119167

168+
std::string SystemPreferences::GetMediaAccessStatus(
169+
const std::string& media_type,
170+
gin_helper::Arguments* args) {
171+
if (media_type == "camera") {
172+
return ConvertDeviceAccessStatus(
173+
GetDeviceAccessStatus(DeviceClass::DeviceClass_VideoCapture));
174+
} else if (media_type == "microphone") {
175+
return ConvertDeviceAccessStatus(
176+
GetDeviceAccessStatus(DeviceClass::DeviceClass_AudioCapture));
177+
} else if (media_type == "screen") {
178+
return ConvertDeviceAccessStatus(
179+
DeviceAccessStatus::DeviceAccessStatus_Allowed);
180+
} else {
181+
args->ThrowError("Invalid media type");
182+
return std::string();
183+
}
184+
}
185+
120186
void SystemPreferences::InitializeWindow() {
121187
invertered_color_scheme_ = IsInvertedColorScheme();
122188
high_contrast_color_scheme_ = IsHighContrastColorScheme();

spec-main/api-system-preferences-spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ describe('systemPreferences module', () => {
269269
});
270270
});
271271

272-
ifdescribe(process.platform === 'darwin')('systemPreferences.getMediaAccessStatus(mediaType)', () => {
272+
ifdescribe(['win32', 'darwin'].includes(process.platform))('systemPreferences.getMediaAccessStatus(mediaType)', () => {
273273
const statuses = ['not-determined', 'granted', 'denied', 'restricted', 'unknown'];
274274

275275
it('returns an access status for a camera access request', () => {

0 commit comments

Comments
 (0)