Bug 758848 [Linux] Add support for wake_notification and sleep_notification on Linux r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D128619
This commit is contained in:
stransky 2021-10-15 20:15:26 +00:00
Родитель 4793e51a6e
Коммит d5227810fd
2 изменённых файлов: 115 добавлений и 1 удалений

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

@ -21,7 +21,10 @@
#include "GeckoProfiler.h"
#include "nsIPowerManagerService.h"
#ifdef MOZ_ENABLE_DBUS
# include <dbus/dbus-glib-lowlevel.h>
# include <gio/gio.h>
# include "WakeLockListener.h"
# include "nsIObserverService.h"
#endif
#include "gfxPlatform.h"
#include "ScreenHelperGTK.h"
@ -107,6 +110,8 @@ gboolean nsAppShell::EventProcessorCallback(GIOChannel* source,
}
nsAppShell::~nsAppShell() {
StopDBusListening();
mozilla::hal::Shutdown();
if (mTag) g_source_remove(mTag);
@ -114,6 +119,102 @@ nsAppShell::~nsAppShell() {
if (mPipeFDs[1]) close(mPipeFDs[1]);
}
#ifdef MOZ_ENABLE_DBUS
static void SessionSleepCallback(DBusGProxy* aProxy, gboolean aSuspend,
gpointer data) {
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (!observerService) {
return;
}
if (aSuspend) {
// Post sleep_notification
observerService->NotifyObservers(nullptr, NS_WIDGET_SLEEP_OBSERVER_TOPIC,
nullptr);
} else {
// Post wake_notification
observerService->NotifyObservers(nullptr, NS_WIDGET_WAKE_OBSERVER_TOPIC,
nullptr);
}
}
static DBusHandlerResult ConnectionSignalFilter(DBusConnection* aConnection,
DBusMessage* aMessage,
void* aData) {
if (dbus_message_is_signal(aMessage, DBUS_INTERFACE_LOCAL, "Disconnected")) {
auto* appShell = static_cast<nsAppShell*>(aData);
appShell->StopDBusListening();
// We do not return DBUS_HANDLER_RESULT_HANDLED here because the connection
// might be shared and some other filters might want to do something.
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
// Based on
// https://github.com/lcp/NetworkManager/blob/240f47c892b4e935a3e92fc09eb15163d1fa28d8/src/nm-sleep-monitor-systemd.c
// Use login1 to signal sleep and wake notifications.
void nsAppShell::StartDBusListening() {
GError* error = nullptr;
mDBusConnection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
if (!mDBusConnection) {
NS_WARNING(nsPrintfCString("gds: Failed to open connection to bus %s\n",
error->message)
.get());
g_error_free(error);
return;
}
DBusConnection* dbusConnection =
dbus_g_connection_get_connection(mDBusConnection);
// Make sure we do not exit the entire program if DBus connection gets
// lost.
dbus_connection_set_exit_on_disconnect(dbusConnection, false);
// Listening to signals the DBus connection is going to get so we will
// know when it is lost and we will be able to disconnect cleanly.
dbus_connection_add_filter(dbusConnection, ConnectionSignalFilter, this,
nullptr);
mLogin1Proxy = dbus_g_proxy_new_for_name(
mDBusConnection, "org.freedesktop.login1", "/org/freedesktop/login1",
"org.freedesktop.login1.Manager");
if (!mLogin1Proxy) {
NS_WARNING("gds: error-no dbus proxy\n");
return;
}
dbus_g_proxy_add_signal(mLogin1Proxy, "PrepareForSleep", G_TYPE_BOOLEAN,
G_TYPE_INVALID);
dbus_g_proxy_connect_signal(mLogin1Proxy, "PrepareForSleep",
G_CALLBACK(SessionSleepCallback), this, nullptr);
}
void nsAppShell::StopDBusListening() {
// If mDBusConnection isn't initialized, that means we are not really
// listening.
if (!mDBusConnection) {
return;
}
dbus_connection_remove_filter(
dbus_g_connection_get_connection(mDBusConnection), ConnectionSignalFilter,
this);
if (mLogin1Proxy) {
dbus_g_proxy_disconnect_signal(mLogin1Proxy, "PrepareForSleep",
G_CALLBACK(SessionSleepCallback), this);
g_object_unref(mLogin1Proxy);
mLogin1Proxy = nullptr;
}
dbus_g_connection_unref(mDBusConnection);
mDBusConnection = nullptr;
}
#endif
nsresult nsAppShell::Init() {
mozilla::hal::Init();
@ -129,6 +230,8 @@ nsresult nsAppShell::Init() {
NS_WARNING(
"Failed to retrieve PowerManagerService, wakelocks will be broken!");
}
StartDBusListening();
}
#endif

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

@ -11,6 +11,9 @@
#include <glib.h>
#include "nsBaseAppShell.h"
#include "nsCOMPtr.h"
#ifdef MOZ_ENABLE_DBUS
# include <dbus/dbus-glib.h>
#endif
class nsAppShell : public nsBaseAppShell {
public:
@ -20,15 +23,23 @@ class nsAppShell : public nsBaseAppShell {
nsresult Init();
virtual void ScheduleNativeEventCallback() override;
virtual bool ProcessNextNativeEvent(bool mayWait) override;
#ifdef MOZ_ENABLE_DBUS
void StartDBusListening();
void StopDBusListening();
#endif
private:
virtual ~nsAppShell();
static gboolean EventProcessorCallback(GIOChannel* source,
GIOCondition condition, gpointer data);
int mPipeFDs[2];
unsigned mTag;
#ifdef MOZ_ENABLE_DBUS
DBusGConnection* mDBusConnection = nullptr;
DBusGProxy* mLogin1Proxy = nullptr;
#endif
};
#endif /* nsAppShell_h__ */