Files
electron/shell/browser/api/electron_api_power_monitor.h
trop[bot] f4c7a3ff66 fix: prevent use-after-free in PowerMonitor via dangling OS callbacks (#50088)
PowerMonitor registered OS-level callbacks (HWND UserData and
WTS/suspend notifications on Windows, shutdown handler and lock-screen
observer on macOS) but never cleaned them up in its destructor. The JS
layer also only held the native object in a closure-local variable,
allowing GC to reclaim it while those registrations still referenced
freed memory.

Retain the native PowerMonitor at module level in power-monitor.ts so
it cannot be garbage-collected. Add DestroyPlatformSpecificMonitors()
to properly tear down OS registrations on destruction: on Windows,
unregister WTS and suspend notifications, clear GWLP_USERDATA, and
destroy the HWND; on macOS, remove the emitter from the global
MacLockMonitor and reset the Browser shutdown handler.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2026-03-05 17:21:22 -05:00

97 lines
3.0 KiB
C++

// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ELECTRON_SHELL_BROWSER_API_ELECTRON_API_POWER_MONITOR_H_
#define ELECTRON_SHELL_BROWSER_API_ELECTRON_API_POWER_MONITOR_H_
#include "base/power_monitor/power_observer.h"
#include "shell/browser/event_emitter_mixin.h"
#include "shell/common/gin_helper/pinnable.h"
#include "shell/common/gin_helper/wrappable.h"
#include "ui/base/idle/idle.h"
#if BUILDFLAG(IS_LINUX)
#include "shell/browser/lib/power_observer_linux.h"
#endif
namespace electron::api {
class PowerMonitor final : public gin_helper::DeprecatedWrappable<PowerMonitor>,
public gin_helper::EventEmitterMixin<PowerMonitor>,
public gin_helper::Pinnable<PowerMonitor>,
private base::PowerStateObserver,
private base::PowerSuspendObserver,
private base::PowerThermalObserver {
public:
static v8::Local<v8::Value> Create(v8::Isolate* isolate);
// gin_helper::Wrappable
static gin::DeprecatedWrapperInfo kWrapperInfo;
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;
const char* GetTypeName() override;
// disable copy
PowerMonitor(const PowerMonitor&) = delete;
PowerMonitor& operator=(const PowerMonitor&) = delete;
private:
explicit PowerMonitor(v8::Isolate* isolate);
~PowerMonitor() override;
#if BUILDFLAG(IS_LINUX)
void SetListeningForShutdown(bool);
#endif
// Called by native callers.
bool ShouldShutdown();
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
void InitPlatformSpecificMonitors();
void DestroyPlatformSpecificMonitors();
#endif
// base::PowerStateObserver implementations:
void OnBatteryPowerStatusChange(
BatteryPowerStatus battery_power_status) override;
// base::PowerSuspendObserver implementations:
void OnSuspend() override;
void OnResume() override;
// base::PowerThermalObserver
void OnThermalStateChange(DeviceThermalState new_state) override;
void OnSpeedLimitChange(int speed_limit) override;
#if BUILDFLAG(IS_WIN)
// Static callback invoked when a message comes in to our messaging window.
static LRESULT CALLBACK WndProcStatic(HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam);
LRESULT CALLBACK WndProc(HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam);
// The window class of |window_|.
ATOM atom_;
// The handle of the module that contains the window procedure of |window_|.
HMODULE instance_;
// The window used for processing events.
HWND window_;
#endif
#if BUILDFLAG(IS_LINUX)
PowerObserverLinux power_observer_linux_{this};
#endif
};
} // namespace electron::api
#endif // ELECTRON_SHELL_BROWSER_API_ELECTRON_API_POWER_MONITOR_H_