Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Enable APNS registration + notification delivery in macOS apps (#…
- Loading branch information
Showing
11 changed files
with
302 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# pushNotifications | ||
|
||
Process: [Main](../glossary.md#main-process) | ||
|
||
> Register for and receive notifications from remote push notification services | ||
For example, when registering for push notifications via Apple push notification services (APNS): | ||
|
||
```javascript | ||
const { pushNotifications, Notification } = require('electron') | ||
|
||
pushNotifications.registerForAPNSNotifications().then((token) => { | ||
// forward token to your remote notification server | ||
}) | ||
|
||
pushNotifications.on('received-apns-notification', (event, userInfo) => { | ||
// generate a new Notification object with the relevant userInfo fields | ||
}) | ||
``` | ||
|
||
## Events | ||
|
||
The `pushNotification` module emits the following events: | ||
|
||
#### Event: 'received-apns-notification' _macOS_ | ||
|
||
Returns: | ||
|
||
* `userInfo` Record<String, any> | ||
|
||
Emitted when the app receives a remote notification while running. | ||
See: https://developer.apple.com/documentation/appkit/nsapplicationdelegate/1428430-application?language=objc | ||
|
||
## Methods | ||
|
||
The `pushNotification` module has the following methods: | ||
|
||
### `pushNotifications.registerForAPNSNotifications()` _macOS_ | ||
|
||
Returns `Promise<string>` | ||
|
||
Registers the app with Apple Push Notification service (APNS) to receive [Badge, Sound, and Alert](https://developer.apple.com/documentation/appkit/sremotenotificationtype?language=objc) notifications. If registration is successful, the promise will be resolved with the APNS device token. Otherwise, the promise will be rejected with an error message. | ||
See: https://developer.apple.com/documentation/appkit/nsapplication/1428476-registerforremotenotificationtyp?language=objc | ||
|
||
### `pushNotifications.unregisterForAPNSNotifications()` _macOS_ | ||
|
||
Unregisters the app from notifications received from APNS. | ||
See: https://developer.apple.com/documentation/appkit/nsapplication/1428747-unregisterforremotenotifications?language=objc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
const { pushNotifications } = process._linkedBinding('electron_browser_push_notifications'); | ||
|
||
export default pushNotifications; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// Copyright (c) 2022 Asana, Inc. | ||
// Use of this source code is governed by the MIT license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "shell/browser/api/electron_api_push_notifications.h" | ||
|
||
#include <string> | ||
|
||
#include "shell/common/gin_converters/value_converter.h" | ||
#include "shell/common/gin_helper/dictionary.h" | ||
#include "shell/common/node_includes.h" | ||
|
||
namespace electron { | ||
|
||
namespace api { | ||
|
||
PushNotifications* g_push_notifications = nullptr; | ||
|
||
gin::WrapperInfo PushNotifications::kWrapperInfo = {gin::kEmbedderNativeGin}; | ||
|
||
PushNotifications::PushNotifications() = default; | ||
|
||
PushNotifications::~PushNotifications() { | ||
g_push_notifications = nullptr; | ||
} | ||
|
||
// static | ||
PushNotifications* PushNotifications::Get() { | ||
if (!g_push_notifications) | ||
g_push_notifications = new PushNotifications(); | ||
return g_push_notifications; | ||
} | ||
|
||
// static | ||
gin::Handle<PushNotifications> PushNotifications::Create(v8::Isolate* isolate) { | ||
return gin::CreateHandle(isolate, PushNotifications::Get()); | ||
} | ||
|
||
// static | ||
gin::ObjectTemplateBuilder PushNotifications::GetObjectTemplateBuilder( | ||
v8::Isolate* isolate) { | ||
auto builder = gin_helper::EventEmitterMixin< | ||
PushNotifications>::GetObjectTemplateBuilder(isolate); | ||
#if BUILDFLAG(IS_MAC) | ||
builder | ||
.SetMethod("registerForAPNSNotifications", | ||
&PushNotifications::RegisterForAPNSNotifications) | ||
.SetMethod("unregisterForAPNSNotifications", | ||
&PushNotifications::UnregisterForAPNSNotifications); | ||
#endif | ||
return builder; | ||
} | ||
|
||
const char* PushNotifications::GetTypeName() { | ||
return "PushNotifications"; | ||
} | ||
|
||
} // namespace api | ||
|
||
} // namespace electron | ||
|
||
namespace { | ||
|
||
void Initialize(v8::Local<v8::Object> exports, | ||
v8::Local<v8::Value> unused, | ||
v8::Local<v8::Context> context, | ||
void* priv) { | ||
v8::Isolate* isolate = context->GetIsolate(); | ||
gin::Dictionary dict(isolate, exports); | ||
dict.Set("pushNotifications", | ||
electron::api::PushNotifications::Create(isolate)); | ||
} | ||
|
||
} // namespace | ||
|
||
NODE_LINKED_MODULE_CONTEXT_AWARE(electron_browser_push_notifications, | ||
Initialize) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// Copyright (c) 2016 GitHub, Inc. | ||
// Use of this source code is governed by the MIT license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef ELECTRON_SHELL_BROWSER_API_ELECTRON_API_PUSH_NOTIFICATIONS_H_ | ||
#define ELECTRON_SHELL_BROWSER_API_ELECTRON_API_PUSH_NOTIFICATIONS_H_ | ||
|
||
#include <string> | ||
|
||
#include <vector> | ||
#include "gin/handle.h" | ||
#include "gin/wrappable.h" | ||
#include "shell/browser/browser_observer.h" | ||
#include "shell/browser/electron_browser_client.h" | ||
#include "shell/browser/event_emitter_mixin.h" | ||
#include "shell/common/gin_helper/promise.h" | ||
|
||
namespace electron { | ||
|
||
namespace api { | ||
|
||
class PushNotifications | ||
: public ElectronBrowserClient::Delegate, | ||
public gin::Wrappable<PushNotifications>, | ||
public gin_helper::EventEmitterMixin<PushNotifications>, | ||
public BrowserObserver { | ||
public: | ||
static PushNotifications* Get(); | ||
static gin::Handle<PushNotifications> Create(v8::Isolate* isolate); | ||
|
||
// gin::Wrappable | ||
static gin::WrapperInfo kWrapperInfo; | ||
gin::ObjectTemplateBuilder GetObjectTemplateBuilder( | ||
v8::Isolate* isolate) override; | ||
const char* GetTypeName() override; | ||
|
||
// disable copy | ||
PushNotifications(const PushNotifications&) = delete; | ||
PushNotifications& operator=(const PushNotifications&) = delete; | ||
|
||
#if BUILDFLAG(IS_MAC) | ||
void OnDidReceiveAPNSNotification(const base::DictionaryValue& user_info); | ||
void ResolveAPNSPromiseSetWithToken(const std::string& token_string); | ||
void RejectAPNSPromiseSetWithError(const std::string& error_message); | ||
#endif | ||
|
||
private: | ||
PushNotifications(); | ||
~PushNotifications() override; | ||
// This set maintains all the promises that should be fulfilled | ||
// once macOS registers, or fails to register, for APNS | ||
std::vector<gin_helper::Promise<std::string>> apns_promise_set_; | ||
|
||
#if BUILDFLAG(IS_MAC) | ||
v8::Local<v8::Promise> RegisterForAPNSNotifications(v8::Isolate* isolate); | ||
void UnregisterForAPNSNotifications(); | ||
#endif | ||
}; | ||
|
||
} // namespace api | ||
|
||
} // namespace electron | ||
|
||
#endif // ELECTRON_SHELL_BROWSER_API_ELECTRON_API_PUSH_NOTIFICATIONS_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright (c) 2022 Asana, Inc. | ||
// Use of this source code is governed by the MIT license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "shell/browser/api/electron_api_push_notifications.h" | ||
|
||
#include <string> | ||
|
||
#include <utility> | ||
#include <vector> | ||
#import "shell/browser/mac/electron_application.h" | ||
#include "shell/common/gin_converters/value_converter.h" | ||
#include "shell/common/gin_helper/promise.h" | ||
|
||
namespace electron { | ||
|
||
namespace api { | ||
|
||
v8::Local<v8::Promise> PushNotifications::RegisterForAPNSNotifications( | ||
v8::Isolate* isolate) { | ||
gin_helper::Promise<std::string> promise(isolate); | ||
v8::Local<v8::Promise> handle = promise.GetHandle(); | ||
|
||
[[AtomApplication sharedApplication] | ||
registerForRemoteNotificationTypes:NSRemoteNotificationTypeBadge | | ||
NSRemoteNotificationTypeAlert | | ||
NSRemoteNotificationTypeSound]; | ||
|
||
PushNotifications::apns_promise_set_.emplace_back(std::move(promise)); | ||
return handle; | ||
} | ||
|
||
void PushNotifications::ResolveAPNSPromiseSetWithToken( | ||
const std::string& token_string) { | ||
std::vector<gin_helper::Promise<std::string>> promises = | ||
std::move(PushNotifications::apns_promise_set_); | ||
for (auto& promise : promises) { | ||
promise.Resolve(token_string); | ||
} | ||
} | ||
|
||
void PushNotifications::RejectAPNSPromiseSetWithError( | ||
const std::string& error_message) { | ||
std::vector<gin_helper::Promise<std::string>> promises = | ||
std::move(PushNotifications::apns_promise_set_); | ||
for (auto& promise : promises) { | ||
promise.RejectWithErrorMessage(error_message); | ||
} | ||
} | ||
|
||
void PushNotifications::UnregisterForAPNSNotifications() { | ||
[[AtomApplication sharedApplication] unregisterForRemoteNotifications]; | ||
} | ||
|
||
void PushNotifications::OnDidReceiveAPNSNotification( | ||
const base::DictionaryValue& user_info) { | ||
Emit("received-apns-notification", user_info); | ||
} | ||
|
||
} // namespace api | ||
|
||
} // namespace electron |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters