* Set name & desktop-entry on Linux notifications

* DBusMock now honors verbose mode flag

* Disable DBus Notification tests on ia32
This commit is contained in:
Charles Kerr 2018-03-12 09:33:06 +09:00 коммит произвёл GitHub
Родитель 9d090e00f2
Коммит 86af20ded0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
9 изменённых файлов: 163 добавлений и 14 удалений

Просмотреть файл

@ -108,14 +108,13 @@ void Browser::SetVersion(const std::string& version) {
}
std::string Browser::GetName() const {
std::string ret = name_override_;
std::string ret = brightray::GetOverriddenApplicationName();
if (ret.empty())
ret = GetExecutableFileProductName();
return ret;
}
void Browser::SetName(const std::string& name) {
name_override_ = name;
brightray::OverrideApplicationName(name);
}

Просмотреть файл

@ -273,8 +273,6 @@ class Browser : public WindowListObserver {
// The browser is being shutdown.
bool is_shutdown_;
std::string name_override_;
int badge_count_ = 0;
#if defined(OS_MACOSX)

Просмотреть файл

@ -18,10 +18,15 @@
namespace {
GDesktopAppInfo* get_desktop_app_info() {
GDesktopAppInfo * ret = nullptr;
std::unique_ptr<base::Environment> env(base::Environment::Create());
const std::string desktop_id = libgtkui::GetDesktopName(env.get());
return desktop_id.empty() ? nullptr
: g_desktop_app_info_new(desktop_id.c_str());
const char * libcc_default_id = "chromium-browser.desktop";
if (!desktop_id.empty() && (desktop_id != libcc_default_id))
ret = g_desktop_app_info_new(desktop_id.c_str());
return ret;
}
} // namespace

Просмотреть файл

@ -8,12 +8,14 @@
#include <string>
#include <vector>
#include "base/environment.h"
#include "base/files/file_enumerator.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "brightray/browser/notification_delegate.h"
#include "brightray/common/application_info.h"
#include "chrome/browser/ui/libgtkui/gtk_util.h"
#include "chrome/browser/ui/libgtkui/skia_utils_gtk.h"
#include "third_party/skia/include/core/SkBitmap.h"
@ -126,6 +128,20 @@ void LibnotifyNotification::Show(const NotificationOptions& options) {
notification_, "x-canonical-append", "true");
}
// Send the desktop name to identify the application
// The desktop-entry is the part before the .desktop
std::unique_ptr<base::Environment> env(base::Environment::Create());
std::string desktop_id = libgtkui::GetDesktopName(env.get());
if (!desktop_id.empty()) {
const std::string suffix{".desktop"};
if (base::EndsWith(desktop_id, suffix,
base::CompareCase::INSENSITIVE_ASCII)) {
desktop_id.resize(desktop_id.size() - suffix.size());
}
libnotify_loader_.notify_notification_set_hint_string(
notification_, "desktop-entry", desktop_id.c_str());
}
GError* error = nullptr;
libnotify_loader_.notify_notification_show(notification_, &error);
if (error) {

Просмотреть файл

@ -7,8 +7,9 @@ namespace {
std::string g_overridden_application_name;
std::string g_overridden_application_version;
}
} // namespace
// name
void OverrideApplicationName(const std::string& name) {
g_overridden_application_name = name;
}
@ -16,6 +17,7 @@ std::string GetOverriddenApplicationName() {
return g_overridden_application_name;
}
// version
void OverrideApplicationVersion(const std::string& version) {
g_overridden_application_version = version;
}

Просмотреть файл

@ -47,10 +47,7 @@ PCWSTR GetRawAppUserModelID() {
if (SUCCEEDED(GetCurrentProcessExplicitAppUserModelID(&current_app_id))) {
g_app_user_model_id = current_app_id;
} else {
std::string name = GetOverriddenApplicationName();
if (name.empty()) {
name = GetApplicationName();
}
std::string name = GetApplicationName();
base::string16 generated_app_id = base::ReplaceStringPlaceholders(
kAppUserModelIDFormat, base::UTF8ToUTF16(name), nullptr);
SetAppUserModelID(generated_app_id);

Просмотреть файл

@ -1,13 +1,22 @@
from config import is_verbose_mode
from dbusmock import DBusTestCase
import atexit
import os
import sys
def cleanup():
DBusTestCase.stop_dbus(DBusTestCase.system_bus_pid)
DBusTestCase.stop_dbus(DBusTestCase.session_bus_pid)
atexit.register(cleanup)
dbusmock_log = sys.stdout if is_verbose_mode() else open(os.devnull, 'w')
DBusTestCase.start_system_bus()
# create a mock for "org.freedesktop.login1" using python-dbusmock
# preconfigured template
(logind_mock, logind) = DBusTestCase.spawn_server_template('logind')
DBusTestCase.spawn_server_template('logind', None, dbusmock_log)
DBusTestCase.start_session_bus()
DBusTestCase.spawn_server_template('notification_daemon', None, dbusmock_log)

Просмотреть файл

@ -38,6 +38,7 @@ def main():
if args.verbose:
enable_verbose_mode()
os.environ['ELECTRON_ENABLE_LOGGING'] = '1'
spec_modules = os.path.join(SOURCE_ROOT, 'spec', 'node_modules')
if args.rebuild_native_modules or not os.path.isdir(spec_modules):

Просмотреть файл

@ -0,0 +1,122 @@
// For these tests we use a fake DBus daemon to verify libnotify interaction
// with the session bus. This requires python-dbusmock to be installed and
// running at $DBUS_SESSION_BUS_ADDRESS.
//
// script/test.py spawns dbusmock, which sets DBUS_SESSION_BUS_ADDRESS.
//
// See https://pypi.python.org/pypi/python-dbusmock to read about dbusmock.
const assert = require('assert')
const dbus = require('dbus-native')
const Promise = require('bluebird')
const {remote} = require('electron')
const {app} = remote.require('electron')
const skip = process.platform !== 'linux' ||
process.arch === 'ia32' ||
!process.env.DBUS_SESSION_BUS_ADDRESS;
(skip ? describe.skip : describe)('Notification module (dbus)', () => {
let mock, Notification, getCalls, reset
const realAppName = app.getName()
const realAppVersion = app.getVersion()
const appName = 'api-notification-dbus-spec'
const serviceName = 'org.freedesktop.Notifications'
before(async () => {
// init app
app.setName(appName)
app.setDesktopName(appName + '.desktop')
// init dbus
const path = '/org/freedesktop/Notifications'
const iface = 'org.freedesktop.DBus.Mock'
const bus = dbus.sessionBus()
console.log('session bus: ' + process.env.DBUS_SESSION_BUS_ADDRESS)
const service = bus.getService(serviceName)
const getInterface = Promise.promisify(service.getInterface, {context: service})
mock = await getInterface(path, iface)
getCalls = Promise.promisify(mock.GetCalls, {context: mock})
reset = Promise.promisify(mock.Reset, {context: mock})
})
after(async () => {
// cleanup dbus
await reset()
// cleanup app
app.setName(realAppName)
app.setVersion(realAppVersion)
})
describe('Notification module using ' + serviceName, () => {
function onMethodCalled (done) {
function cb (name) {
console.log('onMethodCalled: ' + name)
if (name === 'Notify') {
mock.removeListener('MethodCalled', cb)
console.log('done')
done()
}
}
return cb
}
function unmarshalDBusNotifyHints (dbusHints) {
let o = {}
for (let hint of dbusHints) {
let key = hint[0]
let value = hint[1][1][0]
o[key] = value
}
return o
}
function unmarshalDBusNotifyArgs (dbusArgs) {
return {
app_name: dbusArgs[0][1][0],
replaces_id: dbusArgs[1][1][0],
app_icon: dbusArgs[2][1][0],
title: dbusArgs[3][1][0],
body: dbusArgs[4][1][0],
actions: dbusArgs[5][1][0],
hints: unmarshalDBusNotifyHints(dbusArgs[6][1][0])
}
}
before((done) => {
mock.on('MethodCalled', onMethodCalled(done))
// lazy load Notification after we listen to MethodCalled mock signal
Notification = require('electron').remote.Notification
const n = new Notification({
title: 'title',
subtitle: 'subtitle',
body: 'body',
replyPlaceholder: 'replyPlaceholder',
sound: 'sound',
closeButtonText: 'closeButtonText'
})
n.show()
})
it('should call ' + serviceName + ' to show notifications', async () => {
const calls = await getCalls()
assert(calls.length >= 1)
let lastCall = calls[calls.length - 1]
let methodName = lastCall[1]
assert.equal(methodName, 'Notify')
let args = unmarshalDBusNotifyArgs(lastCall[2])
assert.deepEqual(args, {
app_name: appName,
replaces_id: 0,
app_icon: '',
title: 'title',
body: 'body',
actions: [],
hints: {
'append': 'true',
'desktop-entry': appName
}
})
})
})
})