From aec1254a35bd9a3f0099aae77cb46e6f757e2723 Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Fri, 11 Jan 2019 08:48:44 -0800 Subject: [PATCH] fix: don't register some shortcuts without accessibility --- atom/browser/api/atom_api_global_shortcut.cc | 37 ++++++++++++++++++- .../browser/api/atom_api_system_preferences.h | 2 + .../api/atom_api_system_preferences_mac.mm | 6 +++ atom/common/platform_util.h | 1 + atom/common/platform_util_mac.mm | 7 ++++ docs/api/global-shortcut.md | 8 ++++ 6 files changed, 60 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_global_shortcut.cc b/atom/browser/api/atom_api_global_shortcut.cc index 4fc7532d9e346..aee7ea1516853 100644 --- a/atom/browser/api/atom_api_global_shortcut.cc +++ b/atom/browser/api/atom_api_global_shortcut.cc @@ -6,15 +6,45 @@ #include +#include "atom/browser/api/atom_api_system_preferences.h" #include "atom/common/native_mate_converters/accelerator_converter.h" #include "atom/common/native_mate_converters/callback.h" #include "base/stl_util.h" +#include "base/strings/utf_string_conversions.h" #include "native_mate/dictionary.h" #include "atom/common/node_includes.h" +#include "atom/common/platform_util.h" + +#if defined(OS_MACOSX) +#include "base/mac/mac_util.h" +#endif using extensions::GlobalShortcutListener; +namespace { + +#if defined(OS_MACOSX) +bool RegisteringMediaKeyForUntrustedClient(const ui::Accelerator& accelerator) { + if (platform_util::IsAtLeastOS10_14()) { + constexpr ui::KeyboardCode mediaKeys[] = { + ui::VKEY_MEDIA_PLAY_PAUSE, ui::VKEY_MEDIA_NEXT_TRACK, + ui::VKEY_MEDIA_PREV_TRACK, ui::VKEY_MEDIA_STOP}; + + if (std::find(std::begin(mediaKeys), std::end(mediaKeys), + accelerator.key_code()) != std::end(mediaKeys)) { + bool trusted = + atom::api::SystemPreferences::IsTrustedAccessibilityClient(false); + if (!trusted) + return true; + } + } + return false; +} +#endif + +} // namespace + namespace atom { namespace api { @@ -31,7 +61,7 @@ void GlobalShortcut::OnKeyPressed(const ui::Accelerator& accelerator) { if (accelerator_callback_map_.find(accelerator) == accelerator_callback_map_.end()) { // This should never occur, because if it does, GlobalGlobalShortcutListener - // notifes us with wrong accelerator. + // notifies us with wrong accelerator. NOTREACHED(); return; } @@ -40,6 +70,11 @@ void GlobalShortcut::OnKeyPressed(const ui::Accelerator& accelerator) { bool GlobalShortcut::Register(const ui::Accelerator& accelerator, const base::Closure& callback) { +#if defined(OS_MACOSX) + if (RegisteringMediaKeyForUntrustedClient(accelerator)) + return false; +#endif + if (!GlobalShortcutListener::GetInstance()->RegisterAccelerator(accelerator, this)) { return false; diff --git a/atom/browser/api/atom_api_system_preferences.h b/atom/browser/api/atom_api_system_preferences.h index bfd64e80159dc..37671a8e221c4 100644 --- a/atom/browser/api/atom_api_system_preferences.h +++ b/atom/browser/api/atom_api_system_preferences.h @@ -93,6 +93,8 @@ class SystemPreferences : public mate::EventEmitter mate::Arguments* args); void RemoveUserDefault(const std::string& name); bool IsSwipeTrackingFromScrollEventsEnabled(); + + static bool IsTrustedAccessibilityClient(bool prompt); #endif bool IsDarkMode(); bool IsInvertedColorScheme(); diff --git a/atom/browser/api/atom_api_system_preferences_mac.mm b/atom/browser/api/atom_api_system_preferences_mac.mm index 99fb216f5c48e..f26212968647e 100644 --- a/atom/browser/api/atom_api_system_preferences_mac.mm +++ b/atom/browser/api/atom_api_system_preferences_mac.mm @@ -308,6 +308,12 @@ } } +// static +bool SystemPreferences::IsTrustedAccessibilityClient(bool prompt) { + NSDictionary* options = @{(id)kAXTrustedCheckOptionPrompt : @(prompt)}; + return AXIsProcessTrustedWithOptions((CFDictionaryRef)options); +} + void SystemPreferences::RemoveUserDefault(const std::string& name) { NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; [defaults removeObjectForKey:base::SysUTF8ToNSString(name)]; diff --git a/atom/common/platform_util.h b/atom/common/platform_util.h index 6fd84056a06a3..e2549598198e1 100644 --- a/atom/common/platform_util.h +++ b/atom/common/platform_util.h @@ -60,6 +60,7 @@ void Beep(); #if defined(OS_MACOSX) bool GetLoginItemEnabled(); void SetLoginItemEnabled(bool enabled); +bool IsAtLeastOS10_14(); #endif } // namespace platform_util diff --git a/atom/common/platform_util_mac.mm b/atom/common/platform_util_mac.mm index b83b1e11d891e..7150531c5cb62 100644 --- a/atom/common/platform_util_mac.mm +++ b/atom/common/platform_util_mac.mm @@ -8,6 +8,8 @@ #import #import +#include "atom/common/platform_util.h" + #include "base/callback.h" #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -18,6 +20,7 @@ #include "base/strings/stringprintf.h" #include "base/strings/sys_string_conversions.h" #include "net/base/mac/url_conversions.h" +#include "third_party/WebKit/Source/platform/mac/VersionUtilMac.h" #include "url/gurl.h" namespace { @@ -166,6 +169,10 @@ void OpenExternal(const GURL& url, }); } +bool IsAtLeastOS10_14() { + return blink::internal::MacOSXMinorVersion() >= 14; +} + bool MoveItemToTrash(const base::FilePath& full_path) { NSString* path_string = base::SysUTF8ToNSString(full_path.value()); BOOL status = [[NSFileManager defaultManager] diff --git a/docs/api/global-shortcut.md b/docs/api/global-shortcut.md index d0f48a6f8055c..802ef14a2ecb3 100644 --- a/docs/api/global-shortcut.md +++ b/docs/api/global-shortcut.md @@ -54,6 +54,14 @@ When the accelerator is already taken by other applications, this call will silently fail. This behavior is intended by operating systems, since they don't want applications to fight for global shortcuts. +The following accelerators will not be registered successfully on macOS 10.14 Mojave unless +the app has been authorized as a [trusted accessibility client](https://developer.apple.com/library/archive/documentation/Accessibility/Conceptual/AccessibilityMacOSX/OSXAXTestingApps.html): + +* "Media Play/Pause" +* "Media Next Track" +* "Media Previous Track" +* "Media Stop" + ### `globalShortcut.isRegistered(accelerator)` * `accelerator` [Accelerator](accelerator.md)