Skip to content
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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Notifications from the main process #9269

Merged
merged 22 commits into from May 31, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
5dd4d6a
macOS implementation of notifications in the main process
MarshallOfSound Apr 23, 2017
7c38633
Initial semi-working windows implementation
MarshallOfSound Apr 23, 2017
a4bd26f
Fix string16 init on macOS
MarshallOfSound Apr 23, 2017
6bbc4c3
Support Windows 7 notifications from brightray
MarshallOfSound Apr 23, 2017
03688b9
Get image notifications working on Win7 + Win10
MarshallOfSound Apr 24, 2017
c619681
Code cleanup
MarshallOfSound Apr 24, 2017
da31615
Basic linux impl
MarshallOfSound Apr 24, 2017
e7569ed
Remove shell link validation, users should do this themselves
MarshallOfSound May 20, 2017
8815da3
Add Notification API docs
MarshallOfSound May 20, 2017
f5de57d
Mark notification API as experimental
MarshallOfSound May 20, 2017
d1fc832
Update for the brightray move
MarshallOfSound May 22, 2017
193c561
Remove sample notification code
MarshallOfSound May 22, 2017
058bdfb
Use NotificationPresenter - macOS
MarshallOfSound May 29, 2017
c741b58
Remove OS specific implementations
MarshallOfSound May 29, 2017
9aa6b83
Fix compilation and click events on macOS
MarshallOfSound May 29, 2017
6cdfb43
Emit a close event
MarshallOfSound May 29, 2017
5048425
Update implementation as per feedback
MarshallOfSound May 30, 2017
686b138
Fix linting issues
MarshallOfSound May 30, 2017
3938373
Fix linting errors and add isSupported
MarshallOfSound May 30, 2017
227a2bd
Fix reference typed reply placeholder
MarshallOfSound May 30, 2017
5fa2831
Coding style fixes
zcbenz May 31, 2017
9d4588a
Remove test code
zcbenz May 31, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
174 changes: 174 additions & 0 deletions atom/browser/api/atom_api_notification.cc
@@ -0,0 +1,174 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/browser/api/atom_api_notification.h"

#include "atom/browser/api/atom_api_menu.h"
#include "atom/browser/browser.h"
#include "atom/common/native_mate_converters/gfx_converter.h"
#include "atom/common/native_mate_converters/image_converter.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/common/node_includes.h"
#include "base/strings/utf_string_conversions.h"
#include "brightray/browser/browser_client.h"
#include "native_mate/constructor.h"
#include "native_mate/dictionary.h"
#include "url/gurl.h"

namespace atom {

namespace api {

Notification::Notification(v8::Isolate* isolate,
v8::Local<v8::Object> wrapper,
mate::Arguments* args) {
InitWith(isolate, wrapper);

presenter_ = brightray::BrowserClient::Get()->GetNotificationPresenter();

mate::Dictionary opts;
if (args->GetNext(&opts)) {
opts.Get("title", &title_);
opts.Get("body", &body_);
has_icon_ = opts.Get("icon", &icon_);
if (has_icon_) {
opts.Get("icon", &icon_path_);
}
opts.Get("silent", &silent_);
opts.Get("replyPlaceholder", &reply_placeholder_);
opts.Get("hasReply", &has_reply_);
}
}

Notification::~Notification() {
if (notification_)
notification_->set_delegate(nullptr);
}

// static
mate::WrappableBase* Notification::New(mate::Arguments* args) {
if (!Browser::Get()->is_ready()) {
args->ThrowError("Cannot create Notification before app is ready");
return nullptr;
}
return new Notification(args->isolate(), args->GetThis(), args);
}

// Getters
base::string16 Notification::GetTitle() {
return title_;
}

base::string16 Notification::GetBody() {
return body_;
}

bool Notification::GetSilent() {
return silent_;
}

base::string16 Notification::GetReplyPlaceholder() {
return reply_placeholder_;
}

bool Notification::GetHasReply() {
return has_reply_;
}

// Setters
void Notification::SetTitle(const base::string16& new_title) {
title_ = new_title;
}

void Notification::SetBody(const base::string16& new_body) {
body_ = new_body;
}

void Notification::SetSilent(bool new_silent) {
silent_ = new_silent;
}

void Notification::SetReplyPlaceholder(const base::string16& new_placeholder) {
reply_placeholder_ = new_placeholder;
}

void Notification::SetHasReply(bool new_has_reply) {
has_reply_ = new_has_reply;
}

void Notification::NotificationClick() {
Emit("click");
}

void Notification::NotificationReplied(const std::string& reply) {
Emit("reply", reply);
}

void Notification::NotificationDisplayed() {
Emit("show");
}

void Notification::NotificationDestroyed() {
Emit("close");
}

void Notification::NotificationClosed() {
}

// Showing notifications
void Notification::Show() {
if (presenter_) {
notification_ = presenter_->CreateNotification(this);
if (notification_) {
notification_->Show(title_, body_, "", GURL(), icon_.AsBitmap(), silent_,
has_reply_, reply_placeholder_);
}
}
}

bool Notification::IsSupported() {
return !!brightray::BrowserClient::Get()->GetNotificationPresenter();
}

// static
void Notification::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "Notification"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.MakeDestroyable()
.SetMethod("show", &Notification::Show)
.SetProperty("title", &Notification::GetTitle, &Notification::SetTitle)
.SetProperty("body", &Notification::GetBody, &Notification::SetBody)
.SetProperty("silent", &Notification::GetSilent, &Notification::SetSilent)
.SetProperty("replyPlaceholder", &Notification::GetReplyPlaceholder,
&Notification::SetReplyPlaceholder)
.SetProperty("hasReply", &Notification::GetHasReply,
&Notification::SetHasReply);
}

} // namespace api

} // namespace atom

namespace {

using atom::api::Notification;

void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
v8::Isolate* isolate = context->GetIsolate();
Notification::SetConstructor(isolate, base::Bind(&Notification::New));

mate::Dictionary dict(isolate, exports);
dict.Set("Notification",
Notification::GetConstructor(isolate)->GetFunction());

dict.SetMethod("isSupported", &Notification::IsSupported);
}

} // namespace

NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_common_notification, Initialize)
83 changes: 83 additions & 0 deletions atom/browser/api/atom_api_notification.h
@@ -0,0 +1,83 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#ifndef ATOM_BROWSER_API_ATOM_API_NOTIFICATION_H_
#define ATOM_BROWSER_API_ATOM_API_NOTIFICATION_H_

#include <memory>
#include <string>
#include <vector>

#include "atom/browser/api/trackable_object.h"
#include "base/strings/utf_string_conversions.h"
#include "brightray/browser/notification.h"
#include "brightray/browser/notification_delegate.h"
#include "brightray/browser/notification_presenter.h"
#include "native_mate/handle.h"
#include "ui/gfx/image/image.h"

namespace atom {

namespace api {

class Notification : public mate::TrackableObject<Notification>,
public brightray::NotificationDelegate {
public:
static mate::WrappableBase* New(mate::Arguments* args);
static bool IsSupported();

static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);

// NotificationDelegate:
void NotificationClick() override;
void NotificationReplied(const std::string& reply) override;
void NotificationDisplayed() override;
void NotificationDestroyed() override;
void NotificationClosed() override;

protected:
Notification(v8::Isolate* isolate,
v8::Local<v8::Object> wrapper,
mate::Arguments* args);
~Notification() override;

void Show();

// Prop Getters
base::string16 GetTitle();
base::string16 GetBody();
bool GetSilent();
base::string16 GetReplyPlaceholder();
bool GetHasReply();

// Prop Setters
void SetTitle(const base::string16& new_title);
void SetBody(const base::string16& new_body);
void SetSilent(bool new_silent);
void SetReplyPlaceholder(const base::string16& new_reply_placeholder);
void SetHasReply(bool new_has_reply);

private:
base::string16 title_;
base::string16 body_;
gfx::Image icon_;
base::string16 icon_path_;
bool has_icon_ = false;
bool silent_ = false;
base::string16 reply_placeholder_;
bool has_reply_ = false;

brightray::NotificationPresenter* presenter_;

base::WeakPtr<brightray::Notification> notification_;

DISALLOW_COPY_AND_ASSIGN(Notification);
};

} // namespace api

} // namespace atom

#endif // ATOM_BROWSER_API_ATOM_API_NOTIFICATION_H_
1 change: 1 addition & 0 deletions atom/common/node_bindings.cc
Expand Up @@ -56,6 +56,7 @@ REFERENCE_MODULE(atom_common_asar);
REFERENCE_MODULE(atom_common_clipboard);
REFERENCE_MODULE(atom_common_crash_reporter);
REFERENCE_MODULE(atom_common_native_image);
REFERENCE_MODULE(atom_common_notification);
REFERENCE_MODULE(atom_common_screen);
REFERENCE_MODULE(atom_common_shell);
REFERENCE_MODULE(atom_common_v8_util);
Expand Down
2 changes: 1 addition & 1 deletion brightray/browser/browser_client.cc
Expand Up @@ -36,7 +36,7 @@ BrowserClient::~BrowserClient() {

NotificationPresenter* BrowserClient::GetNotificationPresenter() {
if (!notification_presenter_) {
// Create a new presenter if on OS X, Linux, or Windows 8+
// Create a new presenter if on OS X, Linux, or Windows 7+
notification_presenter_.reset(NotificationPresenter::Create());
}
return notification_presenter_.get();
Expand Down
7 changes: 5 additions & 2 deletions brightray/browser/linux/libnotify_notification.cc
Expand Up @@ -88,7 +88,9 @@ void LibnotifyNotification::Show(const base::string16& title,
const std::string& tag,
const GURL& icon_url,
const SkBitmap& icon,
const bool silent) {
bool silent,
bool has_reply,
const base::string16& reply_placeholder) {
notification_ = libnotify_loader_.notify_notification_new(
base::UTF16ToUTF8(title).c_str(),
base::UTF16ToUTF8(body).c_str(),
Expand Down Expand Up @@ -137,7 +139,8 @@ void LibnotifyNotification::Show(const base::string16& title,
return;
}

delegate()->NotificationDisplayed();
if (delegate())
delegate()->NotificationDisplayed();
}

void LibnotifyNotification::Dismiss() {
Expand Down
4 changes: 3 additions & 1 deletion brightray/browser/linux/libnotify_notification.h
Expand Up @@ -27,7 +27,9 @@ class LibnotifyNotification : public Notification {
const std::string& tag,
const GURL& icon_url,
const SkBitmap& icon,
const bool silent) override;
bool silent,
bool has_reply,
const base::string16& reply_placeholder) override;
void Dismiss() override;

private:
Expand Down
5 changes: 4 additions & 1 deletion brightray/browser/mac/cocoa_notification.h
Expand Up @@ -26,10 +26,13 @@ class CocoaNotification : public Notification {
const std::string& tag,
const GURL& icon_url,
const SkBitmap& icon,
const bool silent) override;
bool silent,
const bool has_reply,
const base::string16& reply_placeholder) override;
void Dismiss() override;

void NotificationDisplayed();
void NotificationReplied(const std::string& reply);

NSUserNotification* notification() const { return notification_; }

Expand Down
17 changes: 15 additions & 2 deletions brightray/browser/mac/cocoa_notification.mm
Expand Up @@ -28,7 +28,9 @@
const std::string& tag,
const GURL& icon_url,
const SkBitmap& icon,
const bool silent) {
bool silent,
bool has_reply,
const base::string16& reply_placeholder) {
notification_.reset([[NSUserNotification alloc] init]);
[notification_ setTitle:base::SysUTF16ToNSString(title)];
[notification_ setInformativeText:base::SysUTF16ToNSString(body)];
Expand All @@ -46,6 +48,11 @@
[notification_ setSoundName:NSUserNotificationDefaultSoundName];
}

if (has_reply) {
[notification_ setResponsePlaceholder:base::SysUTF16ToNSString(reply_placeholder)];
[notification_ setHasReplyButton:true];
}

[NSUserNotificationCenter.defaultUserNotificationCenter
deliverNotification:notification_];
}
Expand All @@ -58,7 +65,13 @@
}

void CocoaNotification::NotificationDisplayed() {
delegate()->NotificationDisplayed();
if (delegate())
delegate()->NotificationDisplayed();
}

void CocoaNotification::NotificationReplied(const std::string& reply) {
if (delegate())
delegate()->NotificationReplied(reply);
}

} // namespace brightray
9 changes: 7 additions & 2 deletions brightray/browser/mac/notification_center_delegate.mm
Expand Up @@ -28,8 +28,13 @@ - (void)userNotificationCenter:(NSUserNotificationCenter*)center
- (void)userNotificationCenter:(NSUserNotificationCenter*)center
didActivateNotification:(NSUserNotification *)notif {
auto notification = presenter_->GetNotification(notif);
if (notification)
notification->NotificationClicked();
if (notification) {
if (notif.activationType == NSUserNotificationActivationTypeReplied){
notification->NotificationReplied([notif.response.string UTF8String]);
} else {
notification->NotificationClicked();
}
}
}

- (BOOL)userNotificationCenter:(NSUserNotificationCenter*)center
Expand Down