Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(247)

Unified Diff: content/browser/power_save_blocker_x11.cc

Issue 2075153002: Reland of 'Move content/browser/power_save_blocker to //device/power_save_blocker' (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: missing libs for component mac Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/browser/power_save_blocker_win.cc ('k') | content/browser/renderer_host/render_widget_host_impl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/power_save_blocker_x11.cc
diff --git a/content/browser/power_save_blocker_x11.cc b/content/browser/power_save_blocker_x11.cc
deleted file mode 100644
index a177e392ce1466f2469fe0f76908cd1c09959d7d..0000000000000000000000000000000000000000
--- a/content/browser/power_save_blocker_x11.cc
+++ /dev/null
@@ -1,508 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <X11/Xlib.h>
-#include <X11/extensions/dpms.h>
-#include <X11/extensions/scrnsaver.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "content/browser/power_save_blocker_impl.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/singleton.h"
-#include "base/nix/xdg_util.h"
-#include "base/synchronization/lock.h"
-#include "dbus/bus.h"
-#include "dbus/message.h"
-#include "dbus/object_path.h"
-#include "dbus/object_proxy.h"
-#include "ui/gfx/x/x11_types.h"
-
-namespace {
-
-enum DBusAPI {
- 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.
-// Can be OR'd together and passed as argument to the Inhibit() method
-// to specify which power management features we want to suspend.
-enum GnomeAPIInhibitFlags {
- INHIBIT_LOGOUT = 1,
- INHIBIT_SWITCH_USER = 2,
- INHIBIT_SUSPEND_SESSION = 4,
- INHIBIT_MARK_SESSION_IDLE = 8
-};
-
-const char kGnomeAPIServiceName[] = "org.gnome.SessionManager";
-const char kGnomeAPIInterfaceName[] = "org.gnome.SessionManager";
-const char kGnomeAPIObjectPath[] = "/org/gnome/SessionManager";
-
-const char kFreeDesktopAPIPowerServiceName[] =
- "org.freedesktop.PowerManagement";
-const char kFreeDesktopAPIPowerInterfaceName[] =
- "org.freedesktop.PowerManagement.Inhibit";
-const char kFreeDesktopAPIPowerObjectPath[] =
- "/org/freedesktop/PowerManagement/Inhibit";
-
-const char kFreeDesktopAPIScreenServiceName[] = "org.freedesktop.ScreenSaver";
-const char kFreeDesktopAPIScreenInterfaceName[] = "org.freedesktop.ScreenSaver";
-const char kFreeDesktopAPIScreenObjectPath[] = "/org/freedesktop/ScreenSaver";
-
-} // namespace
-
-namespace content {
-
-class PowerSaveBlockerImpl::Delegate
- : public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> {
- public:
- // Picks an appropriate D-Bus API to use based on the desktop environment.
- Delegate(PowerSaveBlockerType 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 FILE thread.
- void Init();
-
- // 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>;
- ~Delegate() {}
-
- // Selects an appropriate D-Bus API to use for this object. Must be called on
- // the UI thread. Checks enqueue_apply_ once an API has been selected, and
- // enqueues a call back to ApplyBlock() if it is true. See the comments for
- // enqueue_apply_ below.
- void InitOnUIThread();
-
- // Returns true if ApplyBlock() / RemoveBlock() should be called.
- bool ShouldBlock() const;
-
- // Apply or remove the power save block, respectively. These methods should be
- // called once each, on the same thread, per instance. They block waiting for
- // the action to complete (with a timeout); the thread must thus allow I/O.
- void ApplyBlock();
- void RemoveBlock();
-
- // Asynchronous callback functions for ApplyBlock and RemoveBlock.
- // Functions do not receive ownership of |response|.
- void ApplyBlockFinished(dbus::Response* response);
- void RemoveBlockFinished(dbus::Response* response);
-
- // 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);
-
- // If DPMS (the power saving system in X11) is not enabled, then we don't want
- // to try to disable power saving, since on some desktop environments that may
- // enable DPMS with very poor default settings (e.g. turning off the display
- // after only 1 second). Must be called on the UI thread.
- bool DPMSEnabled();
-
- // 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.
- // Must be called on the UI thread, as it may call DPMSEnabled() above.
- DBusAPI SelectAPI();
-
- const PowerSaveBlockerType type_;
- const std::string description_;
- const bool freedesktop_only_;
-
- // Initially, we post a message to the UI thread to select an API. When it
- // finishes, it will post a message to the FILE thread to perform the actual
- // application of the block, unless enqueue_apply_ is false. We set it to
- // false when we post that message, or when RemoveBlock() is called before
- // ApplyBlock() has run. Both api_ and enqueue_apply_ are guarded by lock_.
- DBusAPI api_;
- bool enqueue_apply_;
- base::Lock lock_;
-
- // Indicates that a D-Bus power save blocking request is in flight.
- bool block_inflight_;
- // Used to detect erronous redundant calls to RemoveBlock().
- bool unblock_inflight_;
- // Indicates that RemoveBlock() is called before ApplyBlock() has finished.
- // If it's true, then the RemoveBlock() call will be processed immediately
- // after ApplyBlock() has finished.
- bool enqueue_unblock_;
-
- scoped_refptr<dbus::Bus> bus_;
-
- // 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_;
-
- DISALLOW_COPY_AND_ASSIGN(Delegate);
-};
-
-PowerSaveBlockerImpl::Delegate::Delegate(
- PowerSaveBlockerType 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_(NO_API),
- enqueue_apply_(false),
- 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 FILE thread.
-}
-
-void PowerSaveBlockerImpl::Delegate::Init() {
- base::AutoLock lock(lock_);
- DCHECK(!enqueue_apply_);
- enqueue_apply_ = true;
- block_inflight_ = false;
- unblock_inflight_ = false;
- enqueue_unblock_ = false;
- ui_task_runner_->PostTask(FROM_HERE,
- base::Bind(&Delegate::InitOnUIThread, this));
-}
-
-void PowerSaveBlockerImpl::Delegate::CleanUp() {
- base::AutoLock lock(lock_);
- if (enqueue_apply_) {
- // If a call to ApplyBlock() has not yet been enqueued because we are still
- // initializing on the UI thread, then just cancel it. We don't need to
- // remove the block because we haven't even applied it yet.
- enqueue_apply_ = false;
- } else {
- if (ShouldBlock()) {
- blocking_task_runner_->PostTask(FROM_HERE,
- base::Bind(&Delegate::RemoveBlock, this));
- }
-
- ui_task_runner_->PostTask(
- FROM_HERE, base::Bind(&Delegate::XSSSuspendSet, this, false));
- }
-}
-
-void PowerSaveBlockerImpl::Delegate::InitOnUIThread() {
- DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
- base::AutoLock lock(lock_);
- api_ = SelectAPI();
-
- if (enqueue_apply_) {
- 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::Bind(&Delegate::ApplyBlock, this));
- }
- XSSSuspendSet(true);
- }
- enqueue_apply_ = false;
-}
-
-bool PowerSaveBlockerImpl::Delegate::ShouldBlock() const {
- return freedesktop_only_ ? api_ == FREEDESKTOP_API : api_ != NO_API;
-}
-
-void PowerSaveBlockerImpl::Delegate::ApplyBlock() {
- DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
- DCHECK(!bus_); // ApplyBlock() should only be called once.
- DCHECK(!block_inflight_);
-
- dbus::Bus::Options options;
- options.bus_type = dbus::Bus::SESSION;
- options.connection_type = dbus::Bus::PRIVATE;
- bus_ = new dbus::Bus(options);
-
- scoped_refptr<dbus::ObjectProxy> object_proxy;
- std::unique_ptr<dbus::MethodCall> method_call;
- std::unique_ptr<dbus::MessageWriter> message_writer;
-
- 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
- // reason: The reason for the inhibit
- // flags: Flags that spefify what should be inhibited
- message_writer->AppendString(
- base::CommandLine::ForCurrentProcess()->GetProgram().value());
- message_writer->AppendUint32(0); // should be toplevel_xid
- message_writer->AppendString(description_);
- {
- uint32_t flags = 0;
- switch (type_) {
- case kPowerSaveBlockPreventDisplaySleep:
- flags |= INHIBIT_MARK_SESSION_IDLE;
- flags |= INHIBIT_SUSPEND_SESSION;
- break;
- case kPowerSaveBlockPreventAppSuspension:
- flags |= INHIBIT_SUSPEND_SESSION;
- break;
- }
- message_writer->AppendUint32(flags);
- }
- break;
- case FREEDESKTOP_API:
- switch (type_) {
- case kPowerSaveBlockPreventDisplaySleep:
- object_proxy = bus_->GetObjectProxy(
- kFreeDesktopAPIScreenServiceName,
- dbus::ObjectPath(kFreeDesktopAPIScreenObjectPath));
- method_call.reset(new dbus::MethodCall(
- kFreeDesktopAPIScreenInterfaceName, "Inhibit"));
- break;
- case kPowerSaveBlockPreventAppSuspension:
- 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
- message_writer->AppendString(
- base::CommandLine::ForCurrentProcess()->GetProgram().value());
- message_writer->AppendString(description_);
- break;
- }
-
- block_inflight_ = true;
- object_proxy->CallMethod(
- method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::Bind(&PowerSaveBlockerImpl::Delegate::ApplyBlockFinished, this));
-}
-
-void PowerSaveBlockerImpl::Delegate::ApplyBlockFinished(
- dbus::Response* response) {
- DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
- DCHECK(bus_);
- DCHECK(block_inflight_);
- block_inflight_ = false;
-
- 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);
- if (!message_reader.PopUint32(&inhibit_cookie_))
- LOG(ERROR) << "Invalid Inhibit() response: " << response->ToString();
- } else {
- LOG(ERROR) << "No response to Inhibit() request!";
- }
-
- if (enqueue_unblock_) {
- enqueue_unblock_ = false;
- // RemoveBlock() was called while the Inhibit operation was in flight,
- // so go ahead and remove the block now.
- blocking_task_runner_->PostTask(FROM_HERE,
- base::Bind(&Delegate::RemoveBlock, this));
- }
-}
-
-void PowerSaveBlockerImpl::Delegate::RemoveBlock() {
- DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
- DCHECK(bus_); // RemoveBlock() should only be called once.
- DCHECK(!unblock_inflight_);
-
- if (block_inflight_) {
- DCHECK(!enqueue_unblock_);
- // Can't call RemoveBlock until ApplyBlock's async operation has
- // finished. Enqueue it for execution once ApplyBlock is done.
- enqueue_unblock_ = true;
- return;
- }
-
- 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 kPowerSaveBlockPreventDisplaySleep:
- object_proxy = bus_->GetObjectProxy(
- kFreeDesktopAPIScreenServiceName,
- dbus::ObjectPath(kFreeDesktopAPIScreenObjectPath));
- method_call.reset(new dbus::MethodCall(
- kFreeDesktopAPIScreenInterfaceName, "UnInhibit"));
- break;
- case kPowerSaveBlockPreventAppSuspension:
- 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_);
- unblock_inflight_ = true;
- object_proxy->CallMethod(
- method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
- base::Bind(&PowerSaveBlockerImpl::Delegate::RemoveBlockFinished, this));
-}
-
-void PowerSaveBlockerImpl::Delegate::RemoveBlockFinished(
- dbus::Response* response) {
- DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
- DCHECK(bus_);
- unblock_inflight_ = false;
-
- 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 PowerSaveBlockerImpl::Delegate::XSSSuspendSet(bool suspend) {
- DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
-
- if (!XSSAvailable())
- return;
-
- XDisplay* display = gfx::GetXDisplay();
- XScreenSaverSuspend(display, suspend);
-}
-
-bool PowerSaveBlockerImpl::Delegate::DPMSEnabled() {
- DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
- XDisplay* display = gfx::GetXDisplay();
- BOOL enabled = false;
- int dummy;
- if (DPMSQueryExtension(display, &dummy, &dummy) && DPMSCapable(display)) {
- CARD16 state;
- DPMSInfo(display, &state, &enabled);
- }
- return enabled;
-}
-
-bool PowerSaveBlockerImpl::Delegate::XSSAvailable() {
- DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
- 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 PowerSaveBlockerImpl::Delegate::SelectAPI() {
- DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
- std::unique_ptr<base::Environment> env(base::Environment::Create());
- switch (base::nix::GetDesktopEnvironment(env.get())) {
- case base::nix::DESKTOP_ENVIRONMENT_GNOME:
- case base::nix::DESKTOP_ENVIRONMENT_UNITY:
- if (DPMSEnabled())
- return GNOME_API;
- break;
- case base::nix::DESKTOP_ENVIRONMENT_XFCE:
- case base::nix::DESKTOP_ENVIRONMENT_KDE4:
- case base::nix::DESKTOP_ENVIRONMENT_KDE5:
- if (DPMSEnabled())
- return FREEDESKTOP_API;
- break;
- case base::nix::DESKTOP_ENVIRONMENT_KDE3:
- case base::nix::DESKTOP_ENVIRONMENT_OTHER:
- // Not supported.
- break;
- }
- return NO_API;
-}
-
-PowerSaveBlockerImpl::PowerSaveBlockerImpl(
- PowerSaveBlockerType type,
- Reason reason,
- const std::string& description,
- scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> 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 == kPowerSaveBlockPreventDisplaySleep) {
- freedesktop_suspend_delegate_ = new Delegate(
- kPowerSaveBlockPreventAppSuspension, description,
- true /* freedesktop_only */, ui_task_runner, blocking_task_runner);
- freedesktop_suspend_delegate_->Init();
- }
-}
-
-PowerSaveBlockerImpl::~PowerSaveBlockerImpl() {
- delegate_->CleanUp();
- if (freedesktop_suspend_delegate_)
- freedesktop_suspend_delegate_->CleanUp();
-}
-
-} // namespace content
« no previous file with comments | « content/browser/power_save_blocker_win.cc ('k') | content/browser/renderer_host/render_widget_host_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698