Browse Source

feat: implement systemPreferences.getMediaAccessStatus() on Windows (#24311)

Co-authored-by: Milan Burda <[email protected]>
trop[bot] 4 years ago
parent
commit
39bc7c82a6

+ 4 - 1
docs/api/system-preferences.md

@@ -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.
 
-### `systemPreferences.getMediaAccessStatus(mediaType)` _macOS_
+### `systemPreferences.getMediaAccessStatus(mediaType)` _Windows_ _macOS_
 
 * `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.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_
 
 * `mediaType` String - the type of media being requested; can be `microphone`, `camera`.

+ 2 - 2
shell/browser/api/electron_api_system_preferences.cc

@@ -73,6 +73,8 @@ void SystemPreferences::BuildPrototype(
 #if defined(OS_WIN) || defined(OS_MACOSX)
       .SetMethod("getColor", &SystemPreferences::GetColor)
       .SetMethod("getAccentColor", &SystemPreferences::GetAccentColor)
+      .SetMethod("getMediaAccessStatus",
+                 &SystemPreferences::GetMediaAccessStatus)
 #endif
 
 #if defined(OS_WIN)
@@ -112,8 +114,6 @@ void SystemPreferences::BuildPrototype(
       .SetMethod("promptTouchID", &SystemPreferences::PromptTouchID)
       .SetMethod("isTrustedAccessibilityClient",
                  &SystemPreferences::IsTrustedAccessibilityClient)
-      .SetMethod("getMediaAccessStatus",
-                 &SystemPreferences::GetMediaAccessStatus)
       .SetMethod("askForMediaAccess", &SystemPreferences::AskForMediaAccess)
 #endif
       .SetMethod("isInvertedColorScheme",

+ 2 - 2
shell/browser/api/electron_api_system_preferences.h

@@ -49,6 +49,8 @@ class SystemPreferences : public gin_helper::EventEmitter<SystemPreferences>
   std::string GetAccentColor();
   std::string GetColor(gin_helper::ErrorThrower thrower,
                        const std::string& color);
+  std::string GetMediaAccessStatus(const std::string& media_type,
+                                   gin_helper::Arguments* args);
 #endif
 #if defined(OS_WIN)
   bool IsAeroGlassEnabled();
@@ -99,8 +101,6 @@ class SystemPreferences : public gin_helper::EventEmitter<SystemPreferences>
 
   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,
                                            const std::string& media_type);
 

+ 66 - 0
shell/browser/api/electron_api_system_preferences_win.cc

@@ -3,10 +3,13 @@
 // found in the LICENSE file.
 
 #include <dwmapi.h>
+#include <windows.devices.enumeration.h>
+#include <wrl/client.h>
 #include <iomanip>
 
 #include "shell/browser/api/electron_api_system_preferences.h"
 
+#include "base/win/core_winrt_util.h"
 #include "base/win/wrapped_window_proc.h"
 #include "shell/common/color_util.h"
 #include "ui/base/win/shell.h"
@@ -20,6 +23,51 @@ namespace {
 const wchar_t kSystemPreferencesWindowClass[] =
     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 api {
@@ -117,6 +165,24 @@ std::string SystemPreferences::GetColor(gin_helper::ErrorThrower thrower,
   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() {
   invertered_color_scheme_ = IsInvertedColorScheme();
   high_contrast_color_scheme_ = IsHighContrastColorScheme();

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

@@ -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'];
 
     it('returns an access status for a camera access request', () => {