feat: implement systemPreferences.getMediaAccessStatus() on Windows (#24275)
This commit is contained in:
parent
5b80556da2
commit
9b4572de44
5 changed files with 75 additions and 6 deletions
|
@ -416,7 +416,7 @@ This API itself will not protect your user data; rather, it is a mechanism to al
|
||||||
|
|
||||||
Returns `Boolean` - `true` if the current process is a trusted accessibility client and `false` if it is not.
|
Returns `Boolean` - `true` if the current process is a trusted accessibility client and `false` if it is not.
|
||||||
|
|
||||||
### `systemPreferences.getMediaAccessStatus(mediaType)` _macOS_
|
### `systemPreferences.getMediaAccessStatus(mediaType)` _Windows_ _macOS_
|
||||||
|
|
||||||
* `mediaType` String - Can be `microphone`, `camera` or `screen`.
|
* `mediaType` String - Can be `microphone`, `camera` or `screen`.
|
||||||
|
|
||||||
|
@ -426,6 +426,9 @@ This user consent was not required on macOS 10.13 High Sierra or lower so this m
|
||||||
macOS 10.14 Mojave or higher requires consent for `microphone` and `camera` access.
|
macOS 10.14 Mojave or higher requires consent for `microphone` and `camera` access.
|
||||||
macOS 10.15 Catalina or higher requires consent for `screen` access.
|
macOS 10.15 Catalina or higher requires consent for `screen` access.
|
||||||
|
|
||||||
|
Windows 10 has a global setting controlling `microphone` and `camera` access for all win32 applications.
|
||||||
|
It will always return `granted` for `screen` and for all media types on older versions of Windows.
|
||||||
|
|
||||||
### `systemPreferences.askForMediaAccess(mediaType)` _macOS_
|
### `systemPreferences.askForMediaAccess(mediaType)` _macOS_
|
||||||
|
|
||||||
* `mediaType` String - the type of media being requested; can be `microphone`, `camera`.
|
* `mediaType` String - the type of media being requested; can be `microphone`, `camera`.
|
||||||
|
|
|
@ -73,6 +73,8 @@ void SystemPreferences::BuildPrototype(
|
||||||
#if defined(OS_WIN) || defined(OS_MACOSX)
|
#if defined(OS_WIN) || defined(OS_MACOSX)
|
||||||
.SetMethod("getColor", &SystemPreferences::GetColor)
|
.SetMethod("getColor", &SystemPreferences::GetColor)
|
||||||
.SetMethod("getAccentColor", &SystemPreferences::GetAccentColor)
|
.SetMethod("getAccentColor", &SystemPreferences::GetAccentColor)
|
||||||
|
.SetMethod("getMediaAccessStatus",
|
||||||
|
&SystemPreferences::GetMediaAccessStatus)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
|
@ -112,8 +114,6 @@ void SystemPreferences::BuildPrototype(
|
||||||
.SetMethod("promptTouchID", &SystemPreferences::PromptTouchID)
|
.SetMethod("promptTouchID", &SystemPreferences::PromptTouchID)
|
||||||
.SetMethod("isTrustedAccessibilityClient",
|
.SetMethod("isTrustedAccessibilityClient",
|
||||||
&SystemPreferences::IsTrustedAccessibilityClient)
|
&SystemPreferences::IsTrustedAccessibilityClient)
|
||||||
.SetMethod("getMediaAccessStatus",
|
|
||||||
&SystemPreferences::GetMediaAccessStatus)
|
|
||||||
.SetMethod("askForMediaAccess", &SystemPreferences::AskForMediaAccess)
|
.SetMethod("askForMediaAccess", &SystemPreferences::AskForMediaAccess)
|
||||||
#endif
|
#endif
|
||||||
.SetMethod("isInvertedColorScheme",
|
.SetMethod("isInvertedColorScheme",
|
||||||
|
|
|
@ -49,6 +49,8 @@ class SystemPreferences : public gin_helper::EventEmitter<SystemPreferences>
|
||||||
std::string GetAccentColor();
|
std::string GetAccentColor();
|
||||||
std::string GetColor(gin_helper::ErrorThrower thrower,
|
std::string GetColor(gin_helper::ErrorThrower thrower,
|
||||||
const std::string& color);
|
const std::string& color);
|
||||||
|
std::string GetMediaAccessStatus(const std::string& media_type,
|
||||||
|
gin_helper::Arguments* args);
|
||||||
#endif
|
#endif
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
bool IsAeroGlassEnabled();
|
bool IsAeroGlassEnabled();
|
||||||
|
@ -99,8 +101,6 @@ class SystemPreferences : public gin_helper::EventEmitter<SystemPreferences>
|
||||||
|
|
||||||
static bool IsTrustedAccessibilityClient(bool prompt);
|
static bool IsTrustedAccessibilityClient(bool prompt);
|
||||||
|
|
||||||
std::string GetMediaAccessStatus(const std::string& media_type,
|
|
||||||
gin_helper::Arguments* args);
|
|
||||||
v8::Local<v8::Promise> AskForMediaAccess(v8::Isolate* isolate,
|
v8::Local<v8::Promise> AskForMediaAccess(v8::Isolate* isolate,
|
||||||
const std::string& media_type);
|
const std::string& media_type);
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,13 @@
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include <dwmapi.h>
|
#include <dwmapi.h>
|
||||||
|
#include <windows.devices.enumeration.h>
|
||||||
|
#include <wrl/client.h>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
#include "shell/browser/api/electron_api_system_preferences.h"
|
#include "shell/browser/api/electron_api_system_preferences.h"
|
||||||
|
|
||||||
|
#include "base/win/core_winrt_util.h"
|
||||||
#include "base/win/wrapped_window_proc.h"
|
#include "base/win/wrapped_window_proc.h"
|
||||||
#include "shell/common/color_util.h"
|
#include "shell/common/color_util.h"
|
||||||
#include "ui/base/win/shell.h"
|
#include "ui/base/win/shell.h"
|
||||||
|
@ -20,6 +23,51 @@ namespace {
|
||||||
const wchar_t kSystemPreferencesWindowClass[] =
|
const wchar_t kSystemPreferencesWindowClass[] =
|
||||||
L"Electron_SystemPreferencesHostWindow";
|
L"Electron_SystemPreferencesHostWindow";
|
||||||
|
|
||||||
|
using ABI::Windows::Devices::Enumeration::DeviceAccessStatus;
|
||||||
|
using ABI::Windows::Devices::Enumeration::DeviceClass;
|
||||||
|
using ABI::Windows::Devices::Enumeration::IDeviceAccessInformation;
|
||||||
|
using ABI::Windows::Devices::Enumeration::IDeviceAccessInformationStatics;
|
||||||
|
using Microsoft::WRL::ComPtr;
|
||||||
|
|
||||||
|
DeviceAccessStatus GetDeviceAccessStatus(DeviceClass device_class) {
|
||||||
|
ComPtr<IDeviceAccessInformationStatics> dev_access_info_statics;
|
||||||
|
HRESULT hr = base::win::GetActivationFactory<
|
||||||
|
IDeviceAccessInformationStatics,
|
||||||
|
RuntimeClass_Windows_Devices_Enumeration_DeviceAccessInformation>(
|
||||||
|
&dev_access_info_statics);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
VLOG(1) << "IDeviceAccessInformationStatics failed: " << hr;
|
||||||
|
return DeviceAccessStatus::DeviceAccessStatus_Allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComPtr<IDeviceAccessInformation> dev_access_info;
|
||||||
|
hr = dev_access_info_statics->CreateFromDeviceClass(device_class,
|
||||||
|
&dev_access_info);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
VLOG(1) << "IDeviceAccessInformation failed: " << hr;
|
||||||
|
return DeviceAccessStatus::DeviceAccessStatus_Allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto status = DeviceAccessStatus::DeviceAccessStatus_Unspecified;
|
||||||
|
dev_access_info->get_CurrentStatus(&status);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ConvertDeviceAccessStatus(DeviceAccessStatus value) {
|
||||||
|
switch (value) {
|
||||||
|
case DeviceAccessStatus::DeviceAccessStatus_Unspecified:
|
||||||
|
return "not-determined";
|
||||||
|
case DeviceAccessStatus::DeviceAccessStatus_Allowed:
|
||||||
|
return "granted";
|
||||||
|
case DeviceAccessStatus::DeviceAccessStatus_DeniedBySystem:
|
||||||
|
return "restricted";
|
||||||
|
case DeviceAccessStatus::DeviceAccessStatus_DeniedByUser:
|
||||||
|
return "denied";
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace api {
|
namespace api {
|
||||||
|
@ -117,6 +165,24 @@ std::string SystemPreferences::GetColor(gin_helper::ErrorThrower thrower,
|
||||||
return ToRGBHex(color_utils::GetSysSkColor(id));
|
return ToRGBHex(color_utils::GetSysSkColor(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string SystemPreferences::GetMediaAccessStatus(
|
||||||
|
const std::string& media_type,
|
||||||
|
gin_helper::Arguments* args) {
|
||||||
|
if (media_type == "camera") {
|
||||||
|
return ConvertDeviceAccessStatus(
|
||||||
|
GetDeviceAccessStatus(DeviceClass::DeviceClass_VideoCapture));
|
||||||
|
} else if (media_type == "microphone") {
|
||||||
|
return ConvertDeviceAccessStatus(
|
||||||
|
GetDeviceAccessStatus(DeviceClass::DeviceClass_AudioCapture));
|
||||||
|
} else if (media_type == "screen") {
|
||||||
|
return ConvertDeviceAccessStatus(
|
||||||
|
DeviceAccessStatus::DeviceAccessStatus_Allowed);
|
||||||
|
} else {
|
||||||
|
args->ThrowError("Invalid media type");
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SystemPreferences::InitializeWindow() {
|
void SystemPreferences::InitializeWindow() {
|
||||||
invertered_color_scheme_ = IsInvertedColorScheme();
|
invertered_color_scheme_ = IsInvertedColorScheme();
|
||||||
high_contrast_color_scheme_ = IsHighContrastColorScheme();
|
high_contrast_color_scheme_ = IsHighContrastColorScheme();
|
||||||
|
|
|
@ -269,7 +269,7 @@ describe('systemPreferences module', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
ifdescribe(process.platform === 'darwin')('systemPreferences.getMediaAccessStatus(mediaType)', () => {
|
ifdescribe(['win32', 'darwin'].includes(process.platform))('systemPreferences.getMediaAccessStatus(mediaType)', () => {
|
||||||
const statuses = ['not-determined', 'granted', 'denied', 'restricted', 'unknown'];
|
const statuses = ['not-determined', 'granted', 'denied', 'restricted', 'unknown'];
|
||||||
|
|
||||||
it('returns an access status for a camera access request', () => {
|
it('returns an access status for a camera access request', () => {
|
||||||
|
|
Loading…
Add table
Reference in a new issue