From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shelley Vohr <shelley.vohr@gmail.com>
Date: Mon, 16 Aug 2021 17:55:32 +0200
Subject: fix: media key usage with globalShortcuts

This patch enables media keys to work properly with Electron's globalShortcut
module. Chromium's default usage of RemoteCommandCenterDelegate on macOS falls
down into MPRemoteCommandCenter, which makes it such that an app will not
receive remote control events until it begins playing audio. This runs
counter to the design of globalShortcuts, and so we need to instead
use `ui::MediaKeysListener`.

diff --git a/content/browser/media/media_keys_listener_manager_impl.cc b/content/browser/media/media_keys_listener_manager_impl.cc
index 42e37564e585987d367921568f0f1d2b7507f953..9baf89efbade01e8b60c579255f10799914e144f 100644
--- a/content/browser/media/media_keys_listener_manager_impl.cc
+++ b/content/browser/media/media_keys_listener_manager_impl.cc
@@ -87,7 +87,11 @@ bool MediaKeysListenerManagerImpl::StartWatchingMediaKey(
       CanActiveMediaSessionControllerReceiveEvents();
 
   // Tell the underlying MediaKeysListener to listen for the key.
-  if (should_start_watching && media_keys_listener_ &&
+  if (
+#if BUILDFLAG(IS_MAC)
+      !media_key_handling_enabled_ &&
+#endif  // BUILDFLAG(IS_MAC)
+      should_start_watching && media_keys_listener_ &&
       !media_keys_listener_->StartWatchingMediaKey(key_code)) {
     return false;
   }
@@ -361,6 +365,20 @@ void MediaKeysListenerManagerImpl::StartListeningForMediaKeysIfNecessary() {
         this, ui::MediaKeysListener::Scope::kGlobal);
     DCHECK(media_keys_listener_);
   }
+
+#if BUILDFLAG(IS_MAC)
+  // Chromium's implementation of SystemMediaControls falls
+  // down into MPRemoteCommandCenter, which makes it such that an app will not
+  // will not receive remote control events until it begins playing audio.
+  // If there's not already a MediaKeysListener instance, create one so
+  // that globalShortcuts work correctly.
+  if (!media_keys_listener_) {
+    media_keys_listener_ = ui::MediaKeysListener::Create(
+        this, ui::MediaKeysListener::Scope::kGlobal);
+    DCHECK(media_keys_listener_);
+  }
+#endif
+
   EnsureAuxiliaryServices();
 }
 
diff --git a/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener.cc b/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener.cc
index 16b11c6115cc5504dbd15d58c4b9786633e90e96..7c0a2308d437a2d9cec433c6ab0fd6a9d0c08845 100644
--- a/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener.cc
+++ b/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener.cc
@@ -64,6 +64,22 @@ void GlobalAcceleratorListener::UnregisterAccelerator(
   }
 }
 
+// static
+void GlobalAcceleratorListener::SetShouldUseInternalMediaKeyHandling(bool should_use) {
+  if (content::MediaKeysListenerManager::
+            IsMediaKeysListenerManagerEnabled()) {
+    content::MediaKeysListenerManager* media_keys_listener_manager =
+        content::MediaKeysListenerManager::GetInstance();
+    DCHECK(media_keys_listener_manager);
+
+    if (should_use) {
+      media_keys_listener_manager->EnableInternalMediaKeyHandling();
+    } else {
+      media_keys_listener_manager->DisableInternalMediaKeyHandling();
+    }
+  }
+}
+
 void GlobalAcceleratorListener::UnregisterAccelerators(Observer* observer) {
   if (IsShortcutHandlingSuspended()) {
     return;
diff --git a/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener.h b/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener.h
index 57e35eb71c3f30341ced923af815e6bb78c26da6..96d2e93306c1aaf963744d52451f31e159c7c8b5 100644
--- a/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener.h
+++ b/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener.h
@@ -8,6 +8,7 @@
 #include <map>
 
 #include "base/memory/raw_ptr.h"
+#include "content/public/browser/media_keys_listener_manager.h"
 #include "ui/base/accelerators/command.h"
 #include "ui/gfx/native_ui_types.h"
 
@@ -42,6 +43,9 @@ class GlobalAcceleratorListener {
   // The instance may be nullptr.
   static GlobalAcceleratorListener* GetInstance();
 
+  // enables media keys to work with Electron's globalShortcut module.
+  static void SetShouldUseInternalMediaKeyHandling(bool should_use);
+
   // Register an observer for when a certain `accelerator` is struck. Returns
   // true if register successfully, or false if the specified `accelerator`
   // has been registered by another caller or other native applications.
