refactor: ginify Notification (#22821)

This commit is contained in:
Jeremy Apthorp 2020-03-31 11:42:32 -07:00 committed by GitHub
parent 629465aac7
commit 765c08c600
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 30 deletions

View file

@ -1,10 +1,7 @@
'use strict'; 'use strict';
const { EventEmitter } = require('events');
const { Notification, isSupported } = process.electronBinding('notification'); const { Notification, isSupported } = process.electronBinding('notification');
Object.setPrototypeOf(Notification.prototype, EventEmitter.prototype);
Notification.isSupported = isSupported; Notification.isSupported = isSupported;
module.exports = Notification; module.exports = Notification;

View file

@ -6,6 +6,7 @@
#include "base/guid.h" #include "base/guid.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "gin/handle.h"
#include "shell/browser/api/electron_api_menu.h" #include "shell/browser/api/electron_api_menu.h"
#include "shell/browser/browser.h" #include "shell/browser/browser.h"
#include "shell/browser/electron_browser_client.h" #include "shell/browser/electron_browser_client.h"
@ -48,9 +49,9 @@ namespace electron {
namespace api { namespace api {
Notification::Notification(gin::Arguments* args) { gin::WrapperInfo Notification::kWrapperInfo = {gin::kEmbedderNativeGin};
InitWithArgs(args);
Notification::Notification(gin::Arguments* args) {
presenter_ = static_cast<ElectronBrowserClient*>(ElectronBrowserClient::Get()) presenter_ = static_cast<ElectronBrowserClient*>(ElectronBrowserClient::Get())
->GetNotificationPresenter(); ->GetNotificationPresenter();
@ -80,13 +81,13 @@ Notification::~Notification() {
} }
// static // static
gin_helper::WrappableBase* Notification::New(gin_helper::ErrorThrower thrower, gin::Handle<Notification> Notification::New(gin_helper::ErrorThrower thrower,
gin::Arguments* args) { gin::Arguments* args) {
if (!Browser::Get()->is_ready()) { if (!Browser::Get()->is_ready()) {
thrower.ThrowError("Cannot create Notification before app is ready"); thrower.ThrowError("Cannot create Notification before app is ready");
return nullptr; return gin::Handle<Notification>();
} }
return new Notification(args); return gin::CreateHandle(thrower.isolate(), new Notification(args));
} }
// Getters // Getters
@ -240,12 +241,10 @@ bool Notification::IsSupported() {
->GetNotificationPresenter(); ->GetNotificationPresenter();
} }
// static v8::Local<v8::ObjectTemplate> Notification::FillObjectTemplate(
void Notification::BuildPrototype(v8::Isolate* isolate, v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) { v8::Local<v8::ObjectTemplate> templ) {
prototype->SetClassName(gin::StringToV8(isolate, "Notification")); return gin::ObjectTemplateBuilder(isolate, "Notification", templ)
gin_helper::Destroyable::MakeDestroyable(isolate, prototype);
gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("show", &Notification::Show) .SetMethod("show", &Notification::Show)
.SetMethod("close", &Notification::Close) .SetMethod("close", &Notification::Close)
.SetProperty("title", &Notification::GetTitle, &Notification::SetTitle) .SetProperty("title", &Notification::GetTitle, &Notification::SetTitle)
@ -265,7 +264,8 @@ void Notification::BuildPrototype(v8::Isolate* isolate,
.SetProperty("actions", &Notification::GetActions, .SetProperty("actions", &Notification::GetActions,
&Notification::SetActions) &Notification::SetActions)
.SetProperty("closeButtonText", &Notification::GetCloseButtonText, .SetProperty("closeButtonText", &Notification::GetCloseButtonText,
&Notification::SetCloseButtonText); &Notification::SetCloseButtonText)
.Build();
} }
} // namespace api } // namespace api
@ -281,14 +281,8 @@ void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Context> context, v8::Local<v8::Context> context,
void* priv) { void* priv) {
v8::Isolate* isolate = context->GetIsolate(); v8::Isolate* isolate = context->GetIsolate();
Notification::SetConstructor(isolate,
base::BindRepeating(&Notification::New));
gin_helper::Dictionary dict(isolate, exports); gin_helper::Dictionary dict(isolate, exports);
dict.Set("Notification", Notification::GetConstructor(isolate) dict.Set("Notification", Notification::GetConstructor(context));
->GetFunction(context)
.ToLocalChecked());
dict.SetMethod("isSupported", &Notification::IsSupported); dict.SetMethod("isSupported", &Notification::IsSupported);
} }

View file

@ -10,30 +10,40 @@
#include <vector> #include <vector>
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "gin/wrappable.h"
#include "shell/browser/event_emitter_mixin.h"
#include "shell/browser/notifications/notification.h" #include "shell/browser/notifications/notification.h"
#include "shell/browser/notifications/notification_delegate.h" #include "shell/browser/notifications/notification_delegate.h"
#include "shell/browser/notifications/notification_presenter.h" #include "shell/browser/notifications/notification_presenter.h"
#include "shell/common/gin_helper/cleaned_up_at_exit.h"
#include "shell/common/gin_helper/constructible.h"
#include "shell/common/gin_helper/error_thrower.h" #include "shell/common/gin_helper/error_thrower.h"
#include "shell/common/gin_helper/trackable_object.h"
#include "ui/gfx/image/image.h" #include "ui/gfx/image/image.h"
namespace gin { namespace gin {
class Arguments; class Arguments;
} template <typename T>
class Handle;
} // namespace gin
namespace electron { namespace electron {
namespace api { namespace api {
class Notification : public gin_helper::TrackableObject<Notification>, class Notification : public gin::Wrappable<Notification>,
public gin_helper::EventEmitterMixin<Notification>,
public gin_helper::Constructible<Notification>,
public gin_helper::CleanedUpAtExit,
public NotificationDelegate { public NotificationDelegate {
public: public:
static gin_helper::WrappableBase* New(gin_helper::ErrorThrower thrower,
gin::Arguments* args);
static bool IsSupported(); static bool IsSupported();
static void BuildPrototype(v8::Isolate* isolate, // gin_helper::Constructible
v8::Local<v8::FunctionTemplate> prototype); static gin::Handle<Notification> New(gin_helper::ErrorThrower thrower,
gin::Arguments* args);
static v8::Local<v8::ObjectTemplate> FillObjectTemplate(
v8::Isolate*,
v8::Local<v8::ObjectTemplate>);
// NotificationDelegate: // NotificationDelegate:
void NotificationAction(int index) override; void NotificationAction(int index) override;
@ -43,6 +53,9 @@ class Notification : public gin_helper::TrackableObject<Notification>,
void NotificationDestroyed() override; void NotificationDestroyed() override;
void NotificationClosed() override; void NotificationClosed() override;
// gin::Wrappable
static gin::WrapperInfo kWrapperInfo;
protected: protected:
explicit Notification(gin::Arguments* args); explicit Notification(gin::Arguments* args);
~Notification() override; ~Notification() override;

View file

@ -1,7 +1,13 @@
import { expect } from 'chai'; import { expect } from 'chai';
import { Notification } from 'electron'; import { Notification } from 'electron';
import { emittedOnce } from './events-helpers';
import { ifit } from './spec-helpers';
describe('Notification module', () => { describe('Notification module', () => {
it('is supported', () => {
expect(Notification.isSupported()).to.be.a('boolean');
});
it('inits, gets and sets basic string properties correctly', () => { it('inits, gets and sets basic string properties correctly', () => {
const n = new Notification({ const n = new Notification({
title: 'title', title: 'title',
@ -92,5 +98,33 @@ describe('Notification module', () => {
expect(n.actions[1].text).to.equal('4'); expect(n.actions[1].text).to.equal('4');
}); });
it('can be shown and closed', () => {
const n = new Notification({
title: 'test notification',
body: 'test body',
silent: true
});
n.show();
n.close();
});
ifit(process.platform === 'darwin')('emits show and close events', async () => {
const n = new Notification({
title: 'test notification',
body: 'test body',
silent: true
});
{
const e = emittedOnce(n, 'show');
n.show();
await e;
}
{
const e = emittedOnce(n, 'close');
n.close();
await e;
}
});
// TODO(sethlu): Find way to test init with notification icon? // TODO(sethlu): Find way to test init with notification icon?
}); });