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

Unified Diff: content/browser/power_save_blocker_x11.cc

Issue 1141913002: Make X11 power save suspension calls asynchronous. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 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 | « no previous file | no next file » | 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
index 9cd6113e3f06ddf427460b82a291c5bb085de971..c1be00b7675985ee70e9c210f54e85a3fc49c7d9 100644
--- a/content/browser/power_save_blocker_x11.cc
+++ b/content/browser/power_save_blocker_x11.cc
@@ -93,6 +93,11 @@ class PowerSaveBlockerImpl::Delegate
void ApplyBlock(DBusAPI api);
void RemoveBlock(DBusAPI api);
+ // Asynchronous callback functions for ApplyBlock and RemoveBlock.
+ // Functions do not receive ownership of |response|.
+ void ApplyBlockFinished(DBusAPI api, dbus::Response* response);
+ void RemoveBlockFinished(dbus::Response* response);
+
// 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
@@ -115,6 +120,15 @@ class PowerSaveBlockerImpl::Delegate
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 unblock_enqueued_;
+
scoped_refptr<dbus::Bus> bus_;
// The cookie that identifies our inhibit request,
@@ -139,6 +153,9 @@ void PowerSaveBlockerImpl::Delegate::Init() {
base::AutoLock lock(lock_);
DCHECK(!enqueue_apply_);
enqueue_apply_ = true;
+ block_inflight_ = false;
+ unblock_inflight_ = false;
+ unblock_enqueued_ = false;
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&Delegate::InitOnUIThread, this));
}
@@ -172,7 +189,8 @@ void PowerSaveBlockerImpl::Delegate::InitOnUIThread() {
void PowerSaveBlockerImpl::Delegate::ApplyBlock(DBusAPI api) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- DCHECK(!bus_.get()); // ApplyBlock() should only be called once.
+ DCHECK(!bus_); // ApplyBlock() should only be called once.
+ DCHECK(!block_inflight_);
dbus::Bus::Options options;
options.bus_type = dbus::Bus::SESSION;
@@ -233,26 +251,52 @@ void PowerSaveBlockerImpl::Delegate::ApplyBlock(DBusAPI api) {
break;
}
- // We could do this method call asynchronously, but if we did, we'd need to
- // handle the case where we want to cancel the block before we get a reply.
- // We're on the FILE thread so it should be OK to block briefly here.
- scoped_ptr<dbus::Response> response(object_proxy->CallMethodAndBlock(
- method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
+ block_inflight_ = true;
+ object_proxy->CallMethod(
+ method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+ base::Bind(&PowerSaveBlockerImpl::Delegate::ApplyBlockFinished, this,
+ api));
+}
+
+void PowerSaveBlockerImpl::Delegate::ApplyBlockFinished(
+ DBusAPI api,
+ dbus::Response* response) {
+ DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ 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.get());
+ 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 (unblock_enqueued_) {
+ unblock_enqueued_ = false;
+ // RemoveBlock() was called while the Inhibit operation was in flight,
+ // so go ahead and remove the block now.
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&Delegate::RemoveBlock, this, api_));
+ }
}
void PowerSaveBlockerImpl::Delegate::RemoveBlock(DBusAPI api) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- DCHECK(bus_.get()); // RemoveBlock() should only be called once.
+ DCHECK(bus_); // RemoveBlock() should only be called once.
+ DCHECK(!unblock_inflight_);
+
+ if (block_inflight_) {
+ // Can't call RemoveBlock until ApplyBlock's asynchronous operation has
+ // finished. Enqueue it for execution once ApplyBlock is done.
+ unblock_enqueued_ = true;
miu 2015/05/15 18:43:31 Should you DCHECK(!unblock_enqueued) before this l
Kevin M 2015/05/15 18:55:25 Good idea, done.
+ return;
+ }
scoped_refptr<dbus::ObjectProxy> object_proxy;
scoped_ptr<dbus::MethodCall> method_call;
@@ -279,13 +323,22 @@ void PowerSaveBlockerImpl::Delegate::RemoveBlock(DBusAPI api) {
dbus::MessageWriter message_writer(method_call.get());
message_writer.AppendUint32(inhibit_cookie_);
- scoped_ptr<dbus::Response> response(object_proxy->CallMethodAndBlock(
- method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT));
+ 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_CURRENTLY_ON(BrowserThread::FILE);
+ 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;
miu 2015/05/15 18:43:31 nit: Either leave this in, or adjust the header fi
Kevin M 2015/05/15 18:55:25 Done.
bus_->ShutdownAndBlock();
bus_ = NULL;
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698