electron/shell/browser/lib/power_observer_linux.cc
electron-roller[bot] 55d8b71d72
chore: bump chromium to 141.0.7346.0 (main) (#47983)
* chore: bump chromium in DEPS to 141.0.7341.0

* chore: bump chromium in DEPS to 141.0.7342.0

* chore: update patches

manually resolved conflict in `osr_shared_texture_remove_keyed_mutex_on_win_dxgi.patch` due to https://crrev.com/c/6681354

* 6819541: WebShare: Improve mac share behavior when sharing a URL
https://chromium-review.googlesource.com/c/chromium/src/+/6819541

* Add missing include for SkBitmap

Couldn't quickly find where we lost the full definition in this file's includes. 🤷

* 6771055: [SxS] Move devtools to ContentsContainerView supporting side-by-side.
https://chromium-review.googlesource.com/c/chromium/src/+/6771055

There may be some simplification possible here (set_x, Rect position, ...), but this change is satisfactory to maintain the current behavior.

* 6813689: Switch SystemMemoryInfoKB to use ByteCount
https://chromium-review.googlesource.com/c/chromium/src/+/6813689

* 6818486: Track DevTools feature usage in new badge tracker
https://chromium-review.googlesource.com/c/chromium/src/+/6818486

* chore: bump chromium in DEPS to 141.0.7344.0

* Remove ELECTRON_OZONE_PLATFORM_HINT env var

6819616: Remove OzonePlatformHint | https://chromium-review.googlesource.com/c/chromium/src/+/6819616

See: https://github.com/electron/electron/issues/48001

* chore: update patches

* Add missing include for `base::NumberToString`

* Remove `DESKTOP_STARTUP_ID` code

This was removed upstream in https://chromium-review.googlesource.com/c/chromium/src/+/6819616 and I confirmed with the author that it was an intentional change. Going to mirror upstream and remove it here too.

* chore: bump chromium in DEPS to 141.0.7346.0

* chore: update patches

* 6828465: Reland "Remove BluezDBusThreadManager"
https://chromium-review.googlesource.com/c/chromium/src/+/6828465

* Patch change to Node.js test output

V8 enhanced the stack trace of "thenable" async tasks. A couple of Node.js tests needed to have their snapshots updates to accomodate the extra stack trace frames in the output.

This patch should be upstreamed to Node.js.

See:
6826001: fix thenable async stack trace
https://chromium-review.googlesource.com/c/v8/v8/+/6826001

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: clavin <clavin@electronjs.org>
2025-08-11 12:57:31 +09:00

184 lines
6.2 KiB
C++

// Copyright (c) 2017 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "shell/browser/lib/power_observer_linux.h"
#include <unistd.h>
#include <uv.h>
#include <utility>
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "components/dbus/thread_linux/dbus_thread_linux.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h"
#include "device/bluetooth/dbus/dbus_bluez_manager_wrapper_linux.h"
namespace {
const char kLogindServiceName[] = "org.freedesktop.login1";
const char kLogindObjectPath[] = "/org/freedesktop/login1";
const char kLogindManagerInterface[] = "org.freedesktop.login1.Manager";
base::FilePath::StringType GetExecutableBaseName() {
return base::CommandLine::ForCurrentProcess()
->GetProgram()
.BaseName()
.value();
}
} // namespace
namespace electron {
PowerObserverLinux::PowerObserverLinux(
base::PowerSuspendObserver* suspend_observer)
: suspend_observer_(suspend_observer),
lock_owner_name_(GetExecutableBaseName()) {
if (!bluez::BluezDBusManager::IsInitialized())
bluez::DBusBluezManagerWrapperLinux::Initialize();
auto bus = dbus_thread_linux::GetSharedSystemBus();
if (!bus) {
LOG(WARNING) << "Failed to get system bus connection";
return;
}
// set up the logind proxy
const auto weakThis = weak_ptr_factory_.GetWeakPtr();
logind_ = bus->GetObjectProxy(kLogindServiceName,
dbus::ObjectPath(kLogindObjectPath));
logind_->ConnectToSignal(
kLogindManagerInterface, "PrepareForShutdown",
base::BindRepeating(&PowerObserverLinux::OnPrepareForShutdown, weakThis),
base::BindRepeating(&PowerObserverLinux::OnSignalConnected, weakThis));
logind_->ConnectToSignal(
kLogindManagerInterface, "PrepareForSleep",
base::BindRepeating(&PowerObserverLinux::OnPrepareForSleep, weakThis),
base::BindRepeating(&PowerObserverLinux::OnSignalConnected, weakThis));
logind_->WaitForServiceToBeAvailable(base::BindRepeating(
&PowerObserverLinux::OnLoginServiceAvailable, weakThis));
}
PowerObserverLinux::~PowerObserverLinux() = default;
void PowerObserverLinux::OnLoginServiceAvailable(bool service_available) {
if (!service_available) {
LOG(WARNING) << kLogindServiceName << " not available";
return;
}
// Take sleep inhibit lock
BlockSleep();
}
void PowerObserverLinux::BlockSleep() {
dbus::MethodCall sleep_inhibit_call(kLogindManagerInterface, "Inhibit");
dbus::MessageWriter inhibit_writer(&sleep_inhibit_call);
inhibit_writer.AppendString("sleep"); // what
// Use the executable name as the lock owner, which will list rebrands of the
// electron executable as separate entities.
inhibit_writer.AppendString(lock_owner_name_); // who
inhibit_writer.AppendString("Application cleanup before suspend"); // why
inhibit_writer.AppendString("delay"); // mode
logind_->CallMethod(
&sleep_inhibit_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&PowerObserverLinux::OnInhibitResponse,
weak_ptr_factory_.GetWeakPtr(), &sleep_lock_));
}
void PowerObserverLinux::UnblockSleep() {
sleep_lock_.reset();
}
void PowerObserverLinux::BlockShutdown() {
if (shutdown_lock_.is_valid()) {
LOG(WARNING) << "Trying to subscribe to shutdown multiple times";
return;
}
dbus::MethodCall shutdown_inhibit_call(kLogindManagerInterface, "Inhibit");
dbus::MessageWriter inhibit_writer(&shutdown_inhibit_call);
inhibit_writer.AppendString("shutdown"); // what
inhibit_writer.AppendString(lock_owner_name_); // who
inhibit_writer.AppendString("Ensure a clean shutdown"); // why
inhibit_writer.AppendString("delay"); // mode
logind_->CallMethod(
&shutdown_inhibit_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&PowerObserverLinux::OnInhibitResponse,
weak_ptr_factory_.GetWeakPtr(), &shutdown_lock_));
}
void PowerObserverLinux::UnblockShutdown() {
if (!shutdown_lock_.is_valid()) {
LOG(WARNING)
<< "Trying to unsubscribe to shutdown without being subscribed";
return;
}
shutdown_lock_.reset();
}
void PowerObserverLinux::SetShutdownHandler(
base::RepeatingCallback<bool()> handler) {
// In order to delay system shutdown when e.preventDefault() is invoked
// on a powerMonitor 'shutdown' event, we need an org.freedesktop.login1
// shutdown delay lock. For more details see the "Taking Delay Locks"
// section of https://www.freedesktop.org/wiki/Software/systemd/inhibit/
if (handler && !should_shutdown_) {
BlockShutdown();
} else if (!handler && should_shutdown_) {
UnblockShutdown();
}
should_shutdown_ = std::move(handler);
}
void PowerObserverLinux::OnInhibitResponse(base::ScopedFD* scoped_fd,
dbus::Response* response) {
if (response != nullptr) {
dbus::MessageReader reader(response);
reader.PopFileDescriptor(scoped_fd);
}
}
void PowerObserverLinux::OnPrepareForSleep(dbus::Signal* signal) {
dbus::MessageReader reader(signal);
bool suspending;
if (!reader.PopBool(&suspending)) {
LOG(ERROR) << "Invalid signal: " << signal->ToString();
return;
}
if (suspending) {
suspend_observer_->OnSuspend();
UnblockSleep();
} else {
BlockSleep();
suspend_observer_->OnResume();
}
}
void PowerObserverLinux::OnPrepareForShutdown(dbus::Signal* signal) {
dbus::MessageReader reader(signal);
bool shutting_down;
if (!reader.PopBool(&shutting_down)) {
LOG(ERROR) << "Invalid signal: " << signal->ToString();
return;
}
if (shutting_down) {
if (!should_shutdown_ || should_shutdown_.Run()) {
// The user didn't try to prevent shutdown. Release the lock and allow the
// shutdown to continue normally.
shutdown_lock_.reset();
}
}
}
void PowerObserverLinux::OnSignalConnected(const std::string& /*interface*/,
const std::string& signal,
bool success) {
LOG_IF(WARNING, !success) << "Failed to connect to " << signal;
}
} // namespace electron