blob: 6387f1fe5ebf13d82705df38060eb58d8e81e862 [file] [log] [blame]
/*
* Copyright (C) 2017 Collabora Ltd.
* Copyright (C) 2018 Igalia S.L.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "LowPowerModeNotifier.h"
#include <cstring>
#include <gio/gio.h>
#include <wtf/glib/GUniquePtr.h>
namespace WebCore {
static const char kWarningLevel[] = "WarningLevel";
LowPowerModeNotifier::LowPowerModeNotifier(LowPowerModeChangeCallback&& callback)
: m_cancellable(adoptGRef(g_cancellable_new()))
, m_callback(WTFMove(callback))
{
g_dbus_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, static_cast<GDBusProxyFlags>(G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES),
nullptr, "org.freedesktop.UPower", "/org/freedesktop/UPower/devices/DisplayDevice", "org.freedesktop.UPower.Device", m_cancellable.get(),
[](GObject*, GAsyncResult* result, gpointer userData) {
GUniqueOutPtr<GError> error;
GRefPtr<GDBusProxy> proxy = adoptGRef(g_dbus_proxy_new_for_bus_finish(result, &error.outPtr()));
if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
auto* self = static_cast<LowPowerModeNotifier*>(userData);
if (proxy) {
GUniquePtr<char> nameOwner(g_dbus_proxy_get_name_owner(proxy.get()));
if (nameOwner) {
self->m_displayDeviceProxy = WTFMove(proxy);
self->updateWarningLevel();
g_signal_connect_swapped(self->m_displayDeviceProxy.get(), "g-properties-changed", G_CALLBACK(gPropertiesChangedCallback), self);
return;
}
}
// Now, if there is no name owner, it would be good to try to
// connect to a Flatpak battery status portal instead.
// Unfortunately, no such portal currently exists.
self->m_cancellable = nullptr;
}, this);
}
void LowPowerModeNotifier::updateWarningLevel()
{
GRefPtr<GVariant> variant = adoptGRef(g_dbus_proxy_get_cached_property(m_displayDeviceProxy.get(), kWarningLevel));
if (!variant) {
m_lowPowerModeEnabled = false;
return;
}
// 0: Unknown
// 1: None
// 2: Discharging (only for universal power supplies)
// 3: Low
// 4: Critical
// 5: Action
m_lowPowerModeEnabled = g_variant_get_uint32(variant.get()) > 1;
}
void LowPowerModeNotifier::warningLevelChanged()
{
updateWarningLevel();
m_callback(m_lowPowerModeEnabled);
}
void LowPowerModeNotifier::gPropertiesChangedCallback(LowPowerModeNotifier* self, GVariant* changedProperties)
{
GUniqueOutPtr<GVariantIter> iter;
g_variant_get(changedProperties, "a{sv}", &iter.outPtr());
const char* propertyName;
while (g_variant_iter_next(iter.get(), "{&sv}", &propertyName, nullptr)) {
if (!strcmp(propertyName, kWarningLevel)) {
self->warningLevelChanged();
break;
}
}
}
LowPowerModeNotifier::~LowPowerModeNotifier()
{
g_cancellable_cancel(m_cancellable.get());
}
bool LowPowerModeNotifier::isLowPowerModeEnabled() const
{
return m_lowPowerModeEnabled;
}
} // namespace WebCore