-
Notifications
You must be signed in to change notification settings - Fork 16.2k
feat: Enable APNS registration + notification delivery in macOS apps #33574
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
34 commits
Select commit
Hold shift + click to select a range
d7b5d07
feat: enable APNS registration
joanx bf05601
fix: add APNS register/unregister methods to app
joanx 48f2573
minor wording edit (kick off CircleCI)
joanx 21b0770
fix: lint
joanx d619a96
fix: build errors
joanx 4debddf
fix: undo semantic override
joanx a2f0258
fix: clean up push_notifications header file
joanx b692619
fix: enable pushNotifications module visibility
joanx 7e5f839
fix: WIP resolve build errors
joanx e842356
fix: add types, misc. cleanup
joanx 9af65b5
fix: type reference
joanx 1d60214
fix: cleanup
joanx a1d6309
fix: remove delegate-setting logic
joanx 20fd646
fix: lint
joanx 2fdb31d
fix: build failure
joanx 66cde9e
fix: attempt fix build 2
joanx 5dac57e
force builds
joanx 948fd59
force builds
joanx 563e323
Merge branch 'main' into enable-apns
joanx 662bf3b
fix: rm LICENSES.chromium.html
joanx 30186f7
fix: gen cleanup
joanx c3ea89e
Merge branch 'main' into enable-apns
joanx 5e78aae
fix: decouple implementation from Browser object
joanx 7443a87
fix: cleanup
joanx d590b5a
fix: add general push_notifications module
joanx 220e590
fix: cleanup
joanx 312ba2d
fix: rm unneeded imports
joanx 055fafc
fix: variable renaming + update get handler
joanx 11055ce
fix: cleanup
joanx 8bc184a
fix: lint + update docs
joanx 0508d7b
fix: add example to docs
joanx 90443e5
fix: naming + avoid list mutation
joanx 1d00714
fix: apns_promise_set as class variable
joanx 9802079
fix: lint
joanx File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 | | ||
joanx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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 hidden or 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 hidden or 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 hidden or 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
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.