Commit cd9dd718 authored by Makoto Shimazu's avatar Makoto Shimazu Committed by Commit Bot

Reland "Revert PowerSaveBlockerLinux [2/4]"

This reverts commit abf93b0b.

Reason for revert: a few WakeLockTest are failing probably due to this. Let me try to revert this to see how it'll go.
Sample failing build:
https://ci.chromium.org/p/chromium/builders/ci/Linux%20Tests%20%28dbg%29%281%29/85013

Original change's description:
> Revert "Revert  PowerSaveBlockerLinux [2/4]"
> 
> This reverts commit bbfce899.
> 
> Reason for revert: Issue should be fixed after https://chromium-review.googlesource.com/c/chromium/src/+/1937507/ lands
> 
> Original change's description:
> > Revert  PowerSaveBlockerLinux [2/4]
> > 
> > and the subsequent  PowerSaveBlockerLinux [3/4] and  PowerSaveBlockerLinux [4/4] patches
> > 
> > This reverts commit 2fdeba1b. ("Rewrite PowerSaveBlockerLinux [2/4]")
> > This reverts commit 38fdf074. ("Rewrite PowerSaveBlockerLinux [3/4]")
> > This reverts commit 3bc463b4. ("Rewrite PowerSaveBlockerLinux [4/4]")
> > 
> > The patch caused timeouts in WakeLockTest.ChangeType() and other tests in the services_unittests on
> > Linux Tests (dbg). More details in crbug/1027852.
> > 
> > TBR=thomasanderson@chromium.org
> > 
> > Bug: 1013812,1027852
> > Change-Id: I7688c72f9d9d6c12ff3731f3abde6a05508cfbeb
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1932357
> > Commit-Queue: Tim Schumann <tschumann@chromium.org>
> > Reviewed-by: Tim Schumann <tschumann@chromium.org>
> > Cr-Commit-Position: refs/heads/master@{#718447}
> 
> TBR=thomasanderson@chromium.org,tschumann@chromium.org
> 
> # Not skipping CQ checks because original CL landed > 1 day ago.
> 
> Bug: 1013812, 1027852
> Change-Id: I84a6681cc8ec347587d38f0f5f38ed628e624274
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1937509
> Reviewed-by: Thomas Anderson <thomasanderson@chromium.org>
> Reviewed-by: Tim Schumann <tschumann@chromium.org>
> Commit-Queue: Thomas Anderson <thomasanderson@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#720760}

TBR=thomasanderson@chromium.org,tschumann@chromium.org

Change-Id: I317fd312d0c44b3e59bbada94df3200fa44ae3ac
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 1013812, 1027852
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1947513Reviewed-by: default avatarMakoto Shimazu <shimazu@chromium.org>
Commit-Queue: Makoto Shimazu <shimazu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#720843}
parent f3df187f
......@@ -22,6 +22,12 @@ source_set("power_save_blocker") {
sources = [
"power_save_blocker.h",
"power_save_blocker_android.cc",
"power_save_blocker_chromeos.cc",
"power_save_blocker_mac.cc",
"power_save_blocker_stub.cc",
"power_save_blocker_win.cc",
"power_save_blocker_x11.cc",
]
public_deps = [
......@@ -36,40 +42,48 @@ source_set("power_save_blocker") {
deps += [ "//dbus" ]
}
if (use_x11) {
configs += [ "//build/config/linux:x11" ]
if (!is_chromeos) {
configs += [ "//build/config/linux:xscrnsaver" ]
}
deps += [
"//ui/gfx",
"//ui/gfx/x",
]
}
# Dealing with power_save_blocker_{x11,stub}.cc is a little complicated
# given the interaction between os_chromeos and the feature flags for X11 and
# ozone, so do it all in one spot.
#
# stub implementation is only used at the moment non-chromeOS Ozone platforms
# such as Chromecast.
if (is_chromeos || !use_ozone) {
sources -= [ "power_save_blocker_stub.cc" ]
}
if (is_chromeos || !use_x11 || !use_dbus) {
sources -= [ "power_save_blocker_x11.cc" ]
}
if (is_android) {
sources += [ "power_save_blocker_android.cc" ]
deps += [ ":jni_headers" ]
public_deps += [ "//ui/android" ]
} else if (is_chromeos) {
sources += [ "power_save_blocker_chromeos.cc" ]
}
if (is_chromeos) {
deps += [
"//chromeos/dbus/power",
"//chromeos/dbus/power:power_manager_proto",
]
} else if (is_linux && use_dbus) {
sources += [ "power_save_blocker_linux.cc" ]
deps += [
"//dbus",
"//ui/gfx",
]
if (use_x11) {
configs += [
"//build/config/linux:x11",
"//build/config/linux:xscrnsaver",
]
deps += [ "//ui/gfx/x" ]
}
} else if (is_mac) {
sources += [ "power_save_blocker_mac.cc" ]
}
if (is_mac) {
libs = [
"CoreFoundation.framework",
"IOKit.framework",
]
} else if (is_win) {
sources += [ "power_save_blocker_win.cc" ]
} else {
# Fuchsia and non-DBus Linux.
sources += [ "power_save_blocker_stub.cc" ]
}
}
......
......@@ -61,6 +61,13 @@ class PowerSaveBlocker {
// };
scoped_refptr<Delegate> delegate_;
#if defined(USE_X11)
// Since display sleep prevention also implies system suspend prevention, for
// the Linux FreeDesktop API case, there needs to be a second delegate to
// block system suspend when screen saver / display sleep is blocked.
scoped_refptr<Delegate> freedesktop_suspend_delegate_;
#endif
scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
......
......@@ -2,21 +2,30 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/device/wake_lock/power_save_blocker/power_save_blocker.h"
#include <X11/Xlib.h>
#include <X11/extensions/scrnsaver.h>
#include <stdint.h>
#include <memory>
#include "services/device/wake_lock/power_save_blocker/power_save_blocker.h"
// Xlib #defines Status, but we can't have that for some of our headers.
#ifdef Status
#undef Status
#endif
#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/environment.h"
#include "base/files/file_path.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/singleton.h"
#include "base/nix/xdg_util.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "dbus/bus.h"
......@@ -24,21 +33,14 @@
#include "dbus/object_path.h"
#include "dbus/object_proxy.h"
#include "ui/gfx/switches.h"
#if defined(USE_X11)
#include <X11/extensions/scrnsaver.h>
#include "ui/gfx/x/x11_types.h" // nogncheck
#endif
namespace device {
#include "ui/gfx/x/x11_types.h"
namespace {
enum DBusAPI {
GNOME_API, // org.gnome.SessionManager
FREEDESKTOP_POWER_API, // org.freedesktop.PowerManagement
FREEDESKTOP_SCREENSAVER_API, // org.freedesktop.ScreenSaver
NO_API, // Disable. No supported API available.
GNOME_API, // Use the GNOME API. (Supports more features.)
FREEDESKTOP_API, // Use the FreeDesktop API, for KDE4, KDE5, and XFCE.
};
// Inhibit flags defined in the org.gnome.SessionManager interface.
......@@ -66,132 +68,30 @@ const char kFreeDesktopAPIScreenServiceName[] = "org.freedesktop.ScreenSaver";
const char kFreeDesktopAPIScreenInterfaceName[] = "org.freedesktop.ScreenSaver";
const char kFreeDesktopAPIScreenObjectPath[] = "/org/freedesktop/ScreenSaver";
const char kDbusMethodNameHasOwnerMethod[] = "NameHasOwner";
bool ServiceNameHasOwner(dbus::Bus* bus, const char* service_name) {
dbus::ObjectProxy* dbus_proxy =
bus->GetObjectProxy(DBUS_SERVICE_DBUS, dbus::ObjectPath(DBUS_PATH_DBUS));
dbus::MethodCall name_has_owner_call(DBUS_INTERFACE_DBUS,
kDbusMethodNameHasOwnerMethod);
dbus::MessageWriter writer(&name_has_owner_call);
writer.AppendString(service_name);
std::unique_ptr<dbus::Response> name_has_owner_response =
dbus_proxy->CallMethodAndBlock(&name_has_owner_call,
dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
dbus::MessageReader reader(name_has_owner_response.get());
bool owned = false;
return name_has_owner_response && reader.PopBool(&owned) && owned;
}
bool ShouldPreventDisplaySleep(mojom::WakeLockType type) {
switch (type) {
case mojom::WakeLockType::kPreventAppSuspension:
return false;
case mojom::WakeLockType::kPreventDisplaySleep:
case mojom::WakeLockType::kPreventDisplaySleepAllowDimming:
return true;
}
NOTREACHED();
return false;
}
const char* GetUninhibitMethodName(DBusAPI api) {
switch (api) {
case GNOME_API:
return "Uninhibit";
case FREEDESKTOP_POWER_API:
case FREEDESKTOP_SCREENSAVER_API:
return "UnInhibit";
}
NOTREACHED();
return nullptr;
}
void GetDbusStringsForApi(DBusAPI api,
const char** service_name,
const char** interface_name,
const char** object_path) {
switch (api) {
case GNOME_API:
*service_name = kGnomeAPIServiceName;
*interface_name = kGnomeAPIInterfaceName;
*object_path = kGnomeAPIObjectPath;
return;
case FREEDESKTOP_POWER_API:
*service_name = kFreeDesktopAPIPowerServiceName;
*interface_name = kFreeDesktopAPIPowerInterfaceName;
*object_path = kFreeDesktopAPIPowerObjectPath;
return;
case FREEDESKTOP_SCREENSAVER_API:
*service_name = kFreeDesktopAPIScreenServiceName;
*interface_name = kFreeDesktopAPIScreenInterfaceName;
*object_path = kFreeDesktopAPIScreenObjectPath;
return;
}
NOTREACHED();
}
#if defined(USE_X11)
// Check whether the X11 Screen Saver Extension can be used to disable the
// screen saver. Must be called on the UI thread.
bool X11ScreenSaverAvailable() {
// X Screen Saver isn't accessible in headless mode.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless))
return false;
XDisplay* display = gfx::GetXDisplay();
int dummy;
int major;
int minor;
if (!XScreenSaverQueryExtension(display, &dummy, &dummy))
return false;
if (!XScreenSaverQueryVersion(display, &major, &minor))
return false;
return major > 1 || (major == 1 && minor >= 1);
}
// Wrapper for XScreenSaverSuspend. Checks whether the X11 Screen Saver
// Extension is available first. If it isn't, this is a no-op. Must be called
// on the UI thread.
void X11ScreenSaverSuspendSet(bool suspend) {
if (!X11ScreenSaverAvailable())
return;
XDisplay* display = gfx::GetXDisplay();
XScreenSaverSuspend(display, suspend);
}
#endif
} // namespace
namespace device {
class PowerSaveBlocker::Delegate
: public base::RefCountedThreadSafe<PowerSaveBlocker::Delegate> {
public:
// Picks an appropriate D-Bus API to use based on the desktop environment.
Delegate(mojom::WakeLockType type,
const std::string& description,
bool freedesktop_only,
scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> blocking_task_runner);
// Post a task to initialize the delegate on the UI thread, which will itself
// then post a task to apply the power save block on the blocking task runner.
// then post a task to apply the power save block on the FILE thread.
void Init();
// Post a task to remove the power save block on the blocking task runner,
// unless it hasn't yet been applied, in which case we just prevent it from
// applying.
// Post a task to remove the power save block on the FILE thread, unless it
// hasn't yet been applied, in which case we just prevent it from applying.
void CleanUp();
private:
friend class base::RefCountedThreadSafe<Delegate>;
struct InhibitCookie {
DBusAPI api;
uint32_t cookie;
};
~Delegate() = default;
// Returns true if ApplyBlock() / RemoveBlock() should be called.
......@@ -203,20 +103,31 @@ class PowerSaveBlocker::Delegate
void ApplyBlock();
void RemoveBlock();
// Makes the Inhibit method call. Returns true and saves an entry to
// |inhibit_cookies_| on success.
bool Inhibit(DBusAPI api);
// Wrapper for XScreenSaverSuspend. Checks whether the X11 Screen Saver
// Extension is available first. If it isn't, this is a no-op.
// Must be called on the UI thread.
void XSSSuspendSet(bool suspend);
// Makes the Uninhibit method call given an InhibitCookie saved by a prior
// call to Inhibit().
void Uninhibit(const InhibitCookie& inhibit_cookie);
// If no other method is available (i.e. not running under a Desktop
// Environment) check whether the X11 Screen Saver Extension can be used
// to disable the screen saver. Must be called on the UI thread.
bool XSSAvailable();
// Returns an appropriate D-Bus API to use based on the desktop environment.
DBusAPI SelectAPI();
const mojom::WakeLockType type_;
const std::string description_;
const bool freedesktop_only_;
// Indicates which DBus interface this object uses.
DBusAPI api_;
scoped_refptr<dbus::Bus> bus_;
std::vector<InhibitCookie> inhibit_cookies_;
// The cookie that identifies our inhibit request,
// or 0 if there is no active inhibit request.
uint32_t inhibit_cookie_;
scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> blocking_task_runner_;
......@@ -227,26 +138,32 @@ class PowerSaveBlocker::Delegate
PowerSaveBlocker::Delegate::Delegate(
mojom::WakeLockType type,
const std::string& description,
bool freedesktop_only,
scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> blocking_task_runner)
: type_(type),
description_(description),
freedesktop_only_(freedesktop_only),
api_(SelectAPI()),
inhibit_cookie_(0),
ui_task_runner_(ui_task_runner),
blocking_task_runner_(blocking_task_runner) {
// We're on the client's thread here, so we don't allocate the dbus::Bus
// object yet. We'll do it later in ApplyBlock(), on the blocking task runner.
// object yet. We'll do it later in ApplyBlock(), on the FILE thread.
}
void PowerSaveBlocker::Delegate::Init() {
if (ShouldBlock()) {
// The thread we use here becomes the origin and D-Bus thread for the
// D-Bus library, so we need to use the same thread above for
// RemoveBlock(). It must be a thread that allows I/O operations, so we
// use the FILE thread.
blocking_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&Delegate::ApplyBlock, this));
}
#if defined(USE_X11)
ui_task_runner_->PostTask(FROM_HERE,
base::BindOnce(X11ScreenSaverSuspendSet, true));
#endif
ui_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&Delegate::XSSSuspendSet, this, true));
}
void PowerSaveBlocker::Delegate::CleanUp() {
......@@ -255,16 +172,12 @@ void PowerSaveBlocker::Delegate::CleanUp() {
FROM_HERE, base::BindOnce(&Delegate::RemoveBlock, this));
}
#if defined(USE_X11)
ui_task_runner_->PostTask(FROM_HERE,
base::BindOnce(X11ScreenSaverSuspendSet, false));
#endif
ui_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&Delegate::XSSSuspendSet, this, false));
}
bool PowerSaveBlocker::Delegate::ShouldBlock() const {
// Power saving APIs are not accessible in headless mode.
return !base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kHeadless);
return freedesktop_only_ ? api_ == FREEDESKTOP_API : api_ != NO_API;
}
void PowerSaveBlocker::Delegate::ApplyBlock() {
......@@ -274,53 +187,22 @@ void PowerSaveBlocker::Delegate::ApplyBlock() {
dbus::Bus::Options options;
options.bus_type = dbus::Bus::SESSION;
options.connection_type = dbus::Bus::PRIVATE;
bus_ = base::MakeRefCounted<dbus::Bus>(options);
// First try to inhibit using the GNOME API, since we can inhibit both the
// screensaver and power with one method call.
if (!Inhibit(GNOME_API)) {
// Couldn't inhibit using GNOME, so try the Freedesktop ScreenSaver API
// next, if necessary.
if (ShouldPreventDisplaySleep(type_))
Inhibit(FREEDESKTOP_SCREENSAVER_API);
// For every WakeLockType, we want to inhibit suspend/sleep/etc.
Inhibit(FREEDESKTOP_POWER_API);
}
}
bus_ = new dbus::Bus(options);
void PowerSaveBlocker::Delegate::RemoveBlock() {
DCHECK(blocking_task_runner_->RunsTasksInCurrentSequence());
DCHECK(bus_); // RemoveBlock() should only be called once.
for (const auto& inhibit_cookie : inhibit_cookies_)
Uninhibit(inhibit_cookie);
inhibit_cookies_.clear();
bus_->ShutdownAndBlock();
bus_.reset();
}
bool PowerSaveBlocker::Delegate::Inhibit(DBusAPI api) {
const char* service_name;
const char* interface_name;
const char* object_path;
GetDbusStringsForApi(api, &service_name, &interface_name, &object_path);
// Check that the service name has an owner before making any calls,
// Otherwise if the service does not exist, we will block for the default DBus
// timeout, which can be large on some systems.
if (!ServiceNameHasOwner(bus_.get(), service_name))
return false;
dbus::ObjectProxy* object_proxy =
bus_->GetObjectProxy(service_name, dbus::ObjectPath(object_path));
auto method_call =
std::make_unique<dbus::MethodCall>(interface_name, "Inhibit");
auto message_writer =
std::make_unique<dbus::MessageWriter>(method_call.get());
scoped_refptr<dbus::ObjectProxy> object_proxy;
std::unique_ptr<dbus::MethodCall> method_call;
std::unique_ptr<dbus::MessageWriter> message_writer;
switch (api) {
switch (api_) {
case NO_API:
NOTREACHED(); // We should never call this method with this value.
return;
case GNOME_API:
object_proxy = bus_->GetObjectProxy(
kGnomeAPIServiceName, dbus::ObjectPath(kGnomeAPIObjectPath));
method_call.reset(
new dbus::MethodCall(kGnomeAPIInterfaceName, "Inhibit"));
message_writer.reset(new dbus::MessageWriter(method_call.get()));
// The arguments of the method are:
// app_id: The application identifier
// toplevel_xid: The toplevel X window identifier
......@@ -345,8 +227,25 @@ bool PowerSaveBlocker::Delegate::Inhibit(DBusAPI api) {
message_writer->AppendUint32(flags);
}
break;
case FREEDESKTOP_POWER_API:
case FREEDESKTOP_SCREENSAVER_API:
case FREEDESKTOP_API:
switch (type_) {
case mojom::WakeLockType::kPreventDisplaySleep:
case mojom::WakeLockType::kPreventDisplaySleepAllowDimming:
object_proxy = bus_->GetObjectProxy(
kFreeDesktopAPIScreenServiceName,
dbus::ObjectPath(kFreeDesktopAPIScreenObjectPath));
method_call.reset(new dbus::MethodCall(
kFreeDesktopAPIScreenInterfaceName, "Inhibit"));
break;
case mojom::WakeLockType::kPreventAppSuspension:
object_proxy = bus_->GetObjectProxy(
kFreeDesktopAPIPowerServiceName,
dbus::ObjectPath(kFreeDesktopAPIPowerObjectPath));
method_call.reset(new dbus::MethodCall(
kFreeDesktopAPIPowerInterfaceName, "Inhibit"));
break;
}
message_writer.reset(new dbus::MessageWriter(method_call.get()));
// The arguments of the method are:
// app_id: The application identifier
// reason: The reason for the inhibit
......@@ -359,49 +258,124 @@ bool PowerSaveBlocker::Delegate::Inhibit(DBusAPI api) {
std::unique_ptr<dbus::Response> response = object_proxy->CallMethodAndBlock(
method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
uint32_t cookie;
if (response) {
// The method returns an inhibit_cookie, used to uniquely identify
// this request. It should be used as an argument to Uninhibit()
// in order to remove the request.
dbus::MessageReader message_reader(response.get());
if (!message_reader.PopUint32(&cookie)) {
if (!message_reader.PopUint32(&inhibit_cookie_))
LOG(ERROR) << "Invalid Inhibit() response: " << response->ToString();
return false;
}
} else {
LOG(ERROR) << "No response to Inhibit() request!";
return false;
}
inhibit_cookies_.push_back({api, cookie});
return true;
}
void PowerSaveBlocker::Delegate::Uninhibit(
const InhibitCookie& inhibit_cookie) {
const char* service_name;
const char* interface_name;
const char* object_path;
GetDbusStringsForApi(inhibit_cookie.api, &service_name, &interface_name,
&object_path);
DCHECK(ServiceNameHasOwner(bus_.get(), service_name));
dbus::ObjectProxy* object_proxy =
bus_->GetObjectProxy(service_name, dbus::ObjectPath(object_path));
auto method_call = std::make_unique<dbus::MethodCall>(
interface_name, GetUninhibitMethodName(inhibit_cookie.api));
auto message_writer =
std::make_unique<dbus::MessageWriter>(method_call.get());
message_writer->AppendUint32(inhibit_cookie.cookie);
void PowerSaveBlocker::Delegate::RemoveBlock() {
DCHECK(blocking_task_runner_->RunsTasksInCurrentSequence());
DCHECK(bus_); // RemoveBlock() should only be called once.
scoped_refptr<dbus::ObjectProxy> object_proxy;
std::unique_ptr<dbus::MethodCall> method_call;
switch (api_) {
case NO_API:
NOTREACHED(); // We should never call this method with this value.
return;
case GNOME_API:
object_proxy = bus_->GetObjectProxy(
kGnomeAPIServiceName, dbus::ObjectPath(kGnomeAPIObjectPath));
method_call.reset(
new dbus::MethodCall(kGnomeAPIInterfaceName, "Uninhibit"));
break;
case FREEDESKTOP_API:
switch (type_) {
case mojom::WakeLockType::kPreventDisplaySleep:
case mojom::WakeLockType::kPreventDisplaySleepAllowDimming:
object_proxy = bus_->GetObjectProxy(
kFreeDesktopAPIScreenServiceName,
dbus::ObjectPath(kFreeDesktopAPIScreenObjectPath));
method_call.reset(new dbus::MethodCall(
kFreeDesktopAPIScreenInterfaceName, "UnInhibit"));
break;
case mojom::WakeLockType::kPreventAppSuspension:
object_proxy = bus_->GetObjectProxy(
kFreeDesktopAPIPowerServiceName,
dbus::ObjectPath(kFreeDesktopAPIPowerObjectPath));
method_call.reset(new dbus::MethodCall(
kFreeDesktopAPIPowerInterfaceName, "UnInhibit"));
break;
}
break;
}
dbus::MessageWriter message_writer(method_call.get());
message_writer.AppendUint32(inhibit_cookie_);
std::unique_ptr<dbus::Response> response = object_proxy->CallMethodAndBlock(
method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
// We don't care about checking the result. We assume it works; we can't
// really do anything about it anyway if it fails.
if (!response)
LOG(ERROR) << "No response to Uninhibit() request!";
// We don't care about checking the result. We assume it works; we can't
// really do anything about it anyway if it fails.
inhibit_cookie_ = 0;
bus_->ShutdownAndBlock();
bus_ = nullptr;
}
void PowerSaveBlocker::Delegate::XSSSuspendSet(bool suspend) {
DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
if (!XSSAvailable())
return;
XDisplay* display = gfx::GetXDisplay();
XScreenSaverSuspend(display, suspend);
}
bool PowerSaveBlocker::Delegate::XSSAvailable() {
DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
// X Screen Saver isn't accessible in headless mode.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless))
return false;
XDisplay* display = gfx::GetXDisplay();
int dummy;
int major;
int minor;
if (!XScreenSaverQueryExtension(display, &dummy, &dummy))
return false;
if (!XScreenSaverQueryVersion(display, &major, &minor))
return false;
return major > 1 || (major == 1 && minor >= 1);
}
DBusAPI PowerSaveBlocker::Delegate::SelectAPI() {
// Power saving APIs are not accessible in headless mode.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless))
return NO_API;
// TODO(thomasanderson): Query the GNOME and Freedesktop APIs for availability
// directly rather than guessing based on the desktop environment.
std::unique_ptr<base::Environment> env(base::Environment::Create());
switch (base::nix::GetDesktopEnvironment(env.get())) {
case base::nix::DESKTOP_ENVIRONMENT_CINNAMON:
case base::nix::DESKTOP_ENVIRONMENT_GNOME:
case base::nix::DESKTOP_ENVIRONMENT_PANTHEON:
case base::nix::DESKTOP_ENVIRONMENT_UNITY:
return GNOME_API;
case base::nix::DESKTOP_ENVIRONMENT_XFCE:
case base::nix::DESKTOP_ENVIRONMENT_KDE4:
case base::nix::DESKTOP_ENVIRONMENT_KDE5:
return FREEDESKTOP_API;
case base::nix::DESKTOP_ENVIRONMENT_KDE3:
case base::nix::DESKTOP_ENVIRONMENT_OTHER:
// Not supported.
break;
}
return NO_API;
}
PowerSaveBlocker::PowerSaveBlocker(
......@@ -410,17 +384,28 @@ PowerSaveBlocker::PowerSaveBlocker(
const std::string& description,
scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> blocking_task_runner)
: delegate_(base::MakeRefCounted<Delegate>(type,
description,
ui_task_runner,
blocking_task_runner)),
: delegate_(new Delegate(type,
description,
false /* freedesktop_only */,
ui_task_runner,
blocking_task_runner)),
ui_task_runner_(ui_task_runner),
blocking_task_runner_(blocking_task_runner) {
delegate_->Init();
if (type == mojom::WakeLockType::kPreventDisplaySleep ||
type == mojom::WakeLockType::kPreventDisplaySleepAllowDimming) {
freedesktop_suspend_delegate_ = new Delegate(
mojom::WakeLockType::kPreventAppSuspension, description,
true /* freedesktop_only */, ui_task_runner, blocking_task_runner);
freedesktop_suspend_delegate_->Init();
}
}
PowerSaveBlocker::~PowerSaveBlocker() {
delegate_->CleanUp();
if (freedesktop_suspend_delegate_)
freedesktop_suspend_delegate_->CleanUp();
}
} // namespace device
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment