From eec12b399abcc5d5a52cb705d29469f574da7f65 Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Thu, 6 Jun 2019 07:47:18 -0700 Subject: [PATCH] feat: promisify systemPreferences notification methods (#18631) * feat: promisify systemPreferences notification methods * correct userInfo typedef --- .../browser/api/atom_api_system_preferences.h | 23 +++--- .../api/atom_api_system_preferences_mac.mm | 72 ++++++++++++------- docs/api/modernization/promisification.md | 3 + docs/api/system-preferences.md | 68 +++++++++++++++--- 4 files changed, 117 insertions(+), 49 deletions(-) diff --git a/atom/browser/api/atom_api_system_preferences.h b/atom/browser/api/atom_api_system_preferences.h index 6465cb3bcc18..da2f9b81b0ae 100644 --- a/atom/browser/api/atom_api_system_preferences.h +++ b/atom/browser/api/atom_api_system_preferences.h @@ -65,25 +65,22 @@ class SystemPreferences : public mate::EventEmitter void OnFinishLaunching(const base::DictionaryValue& launch_info) override; #elif defined(OS_MACOSX) - using NotificationCallback = - base::RepeatingCallback; - void PostNotification(const std::string& name, const base::DictionaryValue& user_info, mate::Arguments* args); - int SubscribeNotification(const std::string& name, - const NotificationCallback& callback); + v8::Local SubscribeNotification(v8::Isolate* isolate, + const std::string& name); void UnsubscribeNotification(int id); void PostLocalNotification(const std::string& name, const base::DictionaryValue& user_info); - int SubscribeLocalNotification(const std::string& name, - const NotificationCallback& callback); + v8::Local SubscribeLocalNotification(v8::Isolate* isolate, + const std::string& name); void UnsubscribeLocalNotification(int request_id); void PostWorkspaceNotification(const std::string& name, const base::DictionaryValue& user_info); - int SubscribeWorkspaceNotification(const std::string& name, - const NotificationCallback& callback); + v8::Local SubscribeWorkspaceNotification( + v8::Isolate* isolate, + const std::string& name); void UnsubscribeWorkspaceNotification(int request_id); v8::Local GetUserDefault(const std::string& name, const std::string& type); @@ -125,9 +122,9 @@ class SystemPreferences : public mate::EventEmitter ~SystemPreferences() override; #if defined(OS_MACOSX) - int DoSubscribeNotification(const std::string& name, - const NotificationCallback& callback, - NotificationCenterKind kind); + void DoSubscribeNotification(const std::string& name, + util::Promise promise, + NotificationCenterKind kind); void DoUnsubscribeNotification(int request_id, NotificationCenterKind kind); #endif diff --git a/atom/browser/api/atom_api_system_preferences_mac.mm b/atom/browser/api/atom_api_system_preferences_mac.mm index 783171731249..9a2e4a16cec9 100644 --- a/atom/browser/api/atom_api_system_preferences_mac.mm +++ b/atom/browser/api/atom_api_system_preferences_mac.mm @@ -26,6 +26,7 @@ #include "base/strings/sys_string_conversions.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/values.h" +#include "native_mate/dictionary.h" #include "native_mate/object_template_builder.h" #include "net/base/mac/url_conversions.h" @@ -131,11 +132,15 @@ void SystemPreferences::PostNotification(const std::string& name, deliverImmediately:immediate]; } -int SystemPreferences::SubscribeNotification( - const std::string& name, - const NotificationCallback& callback) { - return DoSubscribeNotification(name, callback, - kNSDistributedNotificationCenter); +v8::Local SystemPreferences::SubscribeNotification( + v8::Isolate* isolate, + const std::string& name) { + util::Promise promise(isolate); + v8::Local handle = promise.GetHandle(); + + DoSubscribeNotification(name, std::move(promise), + kNSDistributedNotificationCenter); + return handle; } void SystemPreferences::UnsubscribeNotification(int request_id) { @@ -151,10 +156,14 @@ void SystemPreferences::PostLocalNotification( userInfo:DictionaryValueToNSDictionary(user_info)]; } -int SystemPreferences::SubscribeLocalNotification( - const std::string& name, - const NotificationCallback& callback) { - return DoSubscribeNotification(name, callback, kNSNotificationCenter); +v8::Local SystemPreferences::SubscribeLocalNotification( + v8::Isolate* isolate, + const std::string& name) { + util::Promise promise(isolate); + v8::Local handle = promise.GetHandle(); + + DoSubscribeNotification(name, std::move(promise), kNSNotificationCenter); + return handle; } void SystemPreferences::UnsubscribeLocalNotification(int request_id) { @@ -171,23 +180,27 @@ void SystemPreferences::PostWorkspaceNotification( userInfo:DictionaryValueToNSDictionary(user_info)]; } -int SystemPreferences::SubscribeWorkspaceNotification( - const std::string& name, - const NotificationCallback& callback) { - return DoSubscribeNotification(name, callback, - kNSWorkspaceNotificationCenter); +v8::Local SystemPreferences::SubscribeWorkspaceNotification( + v8::Isolate* isolate, + const std::string& name) { + util::Promise promise(isolate); + v8::Local handle = promise.GetHandle(); + + DoSubscribeNotification(name, std::move(promise), + kNSWorkspaceNotificationCenter); + return handle; } void SystemPreferences::UnsubscribeWorkspaceNotification(int request_id) { DoUnsubscribeNotification(request_id, kNSWorkspaceNotificationCenter); } -int SystemPreferences::DoSubscribeNotification( - const std::string& name, - const NotificationCallback& callback, - NotificationCenterKind kind) { +void SystemPreferences::DoSubscribeNotification(const std::string& name, + util::Promise promise, + NotificationCenterKind kind) { int request_id = g_next_id++; - __block NotificationCallback copied_callback = callback; + + __block util::Promise p = std::move(promise); NSNotificationCenter* center; switch (kind) { case kNSDistributedNotificationCenter: @@ -208,18 +221,23 @@ int SystemPreferences::DoSubscribeNotification( object:nil queue:nil usingBlock:^(NSNotification* notification) { - std::unique_ptr user_info = + mate::Dictionary dict = + mate::Dictionary::CreateEmpty(p.isolate()); + dict.Set("id", request_id); + dict.Set("event", base::SysNSStringToUTF8(notification.name)); + + std::unique_ptr info = NSDictionaryToDictionaryValue(notification.userInfo); - if (user_info) { - copied_callback.Run( - base::SysNSStringToUTF8(notification.name), *user_info); + if (info) { + base::Value user_info = + base::Value::FromUniquePtrValue(std::move(info)); + dict.Set("userInfo", user_info); } else { - copied_callback.Run( - base::SysNSStringToUTF8(notification.name), - base::DictionaryValue()); + base::Value empty_dict(base::Value::Type::DICTIONARY); + dict.Set("userInfo", empty_dict); } + std::move(p).Resolve(dict.GetHandle()); }]; - return request_id; } void SystemPreferences::DoUnsubscribeNotification(int request_id, diff --git a/docs/api/modernization/promisification.md b/docs/api/modernization/promisification.md index a56c73966117..cc4e0e38d6f5 100644 --- a/docs/api/modernization/promisification.md +++ b/docs/api/modernization/promisification.md @@ -45,6 +45,9 @@ When a majority of affected functions are migrated, this flag will be enabled by - [ses.clearCache(callback)](https://github.com/electron/electron/blob/master/docs/api/session.md#clearCache) - [ses.getBlobData(identifier, callback)](https://github.com/electron/electron/blob/master/docs/api/session.md#getBlobData) - [shell.openExternal(url[, options, callback])](https://github.com/electron/electron/blob/master/docs/api/shell.md#openExternal) +- [systemPreferences.subscribeNotification(event, callback)](https://github.com/electron/electron/blob/master/docs/api/system-preferences.md#subscribeNotification) +- [systemPreferences.subscribeLocalNotification(event, callback)](https://github.com/electron/electron/blob/master/docs/api/system-preferences.md#subscribeLocalNotification) +- [systemPreferences.subscribeWorkspaceNotification(event, callback)](https://github.com/electron/electron/blob/master/docs/api/system-preferences.md#subscribeWorkspaceNotification) - [webFrame.executeJavaScript(code[, userGesture, callback])](https://github.com/electron/electron/blob/master/docs/api/web-frame.md#executeJavaScript) - [webFrame.executeJavaScriptInIsolatedWorld(worldId, scripts[, userGesture, callback])](https://github.com/electron/electron/blob/master/docs/api/web-frame.md#executeJavaScriptInIsolatedWorld) - [webviewTag.capturePage([rect, ]callback)](https://github.com/electron/electron/blob/master/docs/api/webview-tag.md#capturePage) diff --git a/docs/api/system-preferences.md b/docs/api/system-preferences.md index b0e04de163ab..d7c09ffd8ff0 100644 --- a/docs/api/system-preferences.md +++ b/docs/api/system-preferences.md @@ -62,7 +62,7 @@ Returns `Boolean` - Whether the Swipe between pages setting is on. ### `systemPreferences.postNotification(event, userInfo[, deliverImmediately])` _macOS_ * `event` String -* `userInfo` Object +* `userInfo` Record * `deliverImmediately` Boolean (optional) - `true` to post notifications immediately even when the subscribing app is inactive. Posts `event` as native notifications of macOS. The `userInfo` is an Object @@ -71,7 +71,7 @@ that contains the user information dictionary sent along with the notification. ### `systemPreferences.postLocalNotification(event, userInfo)` _macOS_ * `event` String -* `userInfo` Object +* `userInfo` Record Posts `event` as native notifications of macOS. The `userInfo` is an Object that contains the user information dictionary sent along with the notification. @@ -79,7 +79,7 @@ that contains the user information dictionary sent along with the notification. ### `systemPreferences.postWorkspaceNotification(event, userInfo)` _macOS_ * `event` String -* `userInfo` Object +* `userInfo` Record Posts `event` as native notifications of macOS. The `userInfo` is an Object that contains the user information dictionary sent along with the notification. @@ -89,7 +89,7 @@ that contains the user information dictionary sent along with the notification. * `event` String * `callback` Function * `event` String - * `userInfo` Object + * `userInfo` Record Returns `Number` - The ID of this subscription @@ -109,43 +109,93 @@ example values of `event` are: * `AppleColorPreferencesChangedNotification` * `AppleShowScrollBarsSettingChanged` +**[Deprecated](modernization/promisification.md)** + +### `systemPreferences.subscribeNotification(event)` _macOS_ + +* `event` String + +Returns `Promise` - Resolves with an object containing the following items: + * `id` Number - The ID of this subscription, which can be used to unsubscribe the +`event`. + * `event` String + * `userInfo` Record + +Subscribes to native notifications of macOS. + +Under the hood this API subscribes to `NSDistributedNotificationCenter`, +example values of `event` are: + +* `AppleInterfaceThemeChangedNotification` +* `AppleAquaColorVariantChanged` +* `AppleColorPreferencesChangedNotification` +* `AppleShowScrollBarsSettingChanged` + ### `systemPreferences.subscribeLocalNotification(event, callback)` _macOS_ * `event` String * `callback` Function * `event` String - * `userInfo` Object + * `userInfo` Record Returns `Number` - The ID of this subscription Same as `subscribeNotification`, but uses `NSNotificationCenter` for local defaults. This is necessary for events such as `NSUserDefaultsDidChangeNotification`. +**[Deprecated](modernization/promisification.md)** + +### `systemPreferences.subscribeLocalNotification(event)` _macOS_ + +* `event` String + +Returns `Promise` - Resolves with an object containing the following items: + * `id` Number - The ID of this subscription + * `event` String + * `userInfo` Record + +Same as `subscribeNotification`, but uses `NSNotificationCenter` for local defaults. +This is necessary for events such as `NSUserDefaultsDidChangeNotification`. + ### `systemPreferences.subscribeWorkspaceNotification(event, callback)` _macOS_ * `event` String * `callback` Function * `event` String - * `userInfo` Object + * `userInfo` Record + +Same as `subscribeNotification`, but uses `NSWorkspace.sharedWorkspace.notificationCenter`. +This is necessary for events such as `NSWorkspaceDidActivateApplicationNotification`. + +**[Deprecated](modernization/promisification.md)** + +### `systemPreferences.subscribeWorkspaceNotification(event)` _macOS_ + +* `event` String + +Returns `Promise` - Resolves with an object containing the following items: + * `id` Number - The ID of this subscription + * `event` String + * `userInfo` Record Same as `subscribeNotification`, but uses `NSWorkspace.sharedWorkspace.notificationCenter`. This is necessary for events such as `NSWorkspaceDidActivateApplicationNotification`. ### `systemPreferences.unsubscribeNotification(id)` _macOS_ -* `id` Integer +* `id` Number Removes the subscriber with `id`. ### `systemPreferences.unsubscribeLocalNotification(id)` _macOS_ -* `id` Integer +* `id` Number Same as `unsubscribeNotification`, but removes the subscriber from `NSNotificationCenter`. ### `systemPreferences.unsubscribeWorkspaceNotification(id)` _macOS_ -* `id` Integer +* `id` Number Same as `unsubscribeNotification`, but removes the subscriber from `NSWorkspace.sharedWorkspace.notificationCenter`.