| 1 | /* |
| 2 | * Copyright (C) 2017 Collabora Ltd. |
| 3 | * Copyright (C) 2018 Igalia S.L. |
| 4 | * |
| 5 | * This library is free software; you can redistribute it and/or |
| 6 | * modify it under the terms of the GNU Lesser General Public |
| 7 | * License as published by the Free Software Foundation; either |
| 8 | * version 2 of the License, or (at your option) any later version. |
| 9 | * |
| 10 | * This library is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 13 | * Lesser General Public License for more details. |
| 14 | * |
| 15 | * You should have received a copy of the GNU Lesser General Public |
| 16 | * License along with this library; if not, write to the Free Software |
| 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 18 | */ |
| 19 | |
| 20 | #include "config.h" |
| 21 | #include "LowPowerModeNotifier.h" |
| 22 | |
| 23 | #include <cstring> |
| 24 | #include <gio/gio.h> |
| 25 | #include <wtf/glib/GUniquePtr.h> |
| 26 | |
| 27 | namespace WebCore { |
| 28 | |
| 29 | static const char kWarningLevel[] = "WarningLevel" ; |
| 30 | |
| 31 | LowPowerModeNotifier::LowPowerModeNotifier(LowPowerModeChangeCallback&& callback) |
| 32 | : m_cancellable(adoptGRef(g_cancellable_new())) |
| 33 | , m_callback(WTFMove(callback)) |
| 34 | { |
| 35 | 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), |
| 36 | nullptr, "org.freedesktop.UPower" , "/org/freedesktop/UPower/devices/DisplayDevice" , "org.freedesktop.UPower.Device" , m_cancellable.get(), |
| 37 | [](GObject*, GAsyncResult* result, gpointer userData) { |
| 38 | GUniqueOutPtr<GError> error; |
| 39 | GRefPtr<GDBusProxy> proxy = adoptGRef(g_dbus_proxy_new_for_bus_finish(result, &error.outPtr())); |
| 40 | if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
| 41 | return; |
| 42 | |
| 43 | auto* self = static_cast<LowPowerModeNotifier*>(userData); |
| 44 | if (proxy) { |
| 45 | GUniquePtr<char> nameOwner(g_dbus_proxy_get_name_owner(proxy.get())); |
| 46 | if (nameOwner) { |
| 47 | self->m_displayDeviceProxy = WTFMove(proxy); |
| 48 | self->updateWarningLevel(); |
| 49 | g_signal_connect_swapped(self->m_displayDeviceProxy.get(), "g-properties-changed" , G_CALLBACK(gPropertiesChangedCallback), self); |
| 50 | return; |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | // Now, if there is no name owner, it would be good to try to |
| 55 | // connect to a Flatpak battery status portal instead. |
| 56 | // Unfortunately, no such portal currently exists. |
| 57 | self->m_cancellable = nullptr; |
| 58 | }, this); |
| 59 | } |
| 60 | |
| 61 | void LowPowerModeNotifier::updateWarningLevel() |
| 62 | { |
| 63 | GRefPtr<GVariant> variant = adoptGRef(g_dbus_proxy_get_cached_property(m_displayDeviceProxy.get(), kWarningLevel)); |
| 64 | if (!variant) { |
| 65 | m_lowPowerModeEnabled = false; |
| 66 | return; |
| 67 | } |
| 68 | |
| 69 | // 0: Unknown |
| 70 | // 1: None |
| 71 | // 2: Discharging (only for universal power supplies) |
| 72 | // 3: Low |
| 73 | // 4: Critical |
| 74 | // 5: Action |
| 75 | m_lowPowerModeEnabled = g_variant_get_uint32(variant.get()) > 1; |
| 76 | } |
| 77 | |
| 78 | void LowPowerModeNotifier::warningLevelChanged() |
| 79 | { |
| 80 | updateWarningLevel(); |
| 81 | m_callback(m_lowPowerModeEnabled); |
| 82 | } |
| 83 | |
| 84 | void LowPowerModeNotifier::gPropertiesChangedCallback(LowPowerModeNotifier* self, GVariant* changedProperties) |
| 85 | { |
| 86 | GUniqueOutPtr<GVariantIter> iter; |
| 87 | g_variant_get(changedProperties, "a{sv}" , &iter.outPtr()); |
| 88 | |
| 89 | const char* propertyName; |
| 90 | while (g_variant_iter_next(iter.get(), "{&sv}" , &propertyName, nullptr)) { |
| 91 | if (!strcmp(propertyName, kWarningLevel)) { |
| 92 | self->warningLevelChanged(); |
| 93 | break; |
| 94 | } |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | LowPowerModeNotifier::~LowPowerModeNotifier() |
| 99 | { |
| 100 | g_cancellable_cancel(m_cancellable.get()); |
| 101 | } |
| 102 | |
| 103 | bool LowPowerModeNotifier::isLowPowerModeEnabled() const |
| 104 | { |
| 105 | return m_lowPowerModeEnabled; |
| 106 | } |
| 107 | |
| 108 | } // namespace WebCore |
| 109 | |