| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <X11/Xlib.h> | 5 #include <X11/Xlib.h> |
| 6 #include <X11/extensions/dpms.h> | 6 #include <X11/extensions/dpms.h> |
| 7 #include <X11/extensions/scrnsaver.h> | 7 #include <X11/extensions/scrnsaver.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <memory> | 10 #include <memory> |
| 11 | 11 |
| 12 #include "content/browser/power_save_blocker_impl.h" | 12 #include "content/browser/power_save_blocker_impl.h" |
| 13 // Xlib #defines Status, but we can't have that for some of our headers. | 13 // Xlib #defines Status, but we can't have that for some of our headers. |
| 14 #ifdef Status | 14 #ifdef Status |
| 15 #undef Status | 15 #undef Status |
| 16 #endif | 16 #endif |
| 17 | 17 |
| 18 #include "base/bind.h" | 18 #include "base/bind.h" |
| 19 #include "base/callback.h" | 19 #include "base/callback.h" |
| 20 #include "base/command_line.h" | 20 #include "base/command_line.h" |
| 21 #include "base/environment.h" | 21 #include "base/environment.h" |
| 22 #include "base/files/file_path.h" | 22 #include "base/files/file_path.h" |
| 23 #include "base/location.h" |
| 23 #include "base/logging.h" | 24 #include "base/logging.h" |
| 24 #include "base/macros.h" | 25 #include "base/macros.h" |
| 25 #include "base/memory/ref_counted.h" | 26 #include "base/memory/ref_counted.h" |
| 26 #include "base/memory/singleton.h" | 27 #include "base/memory/singleton.h" |
| 27 #include "base/nix/xdg_util.h" | 28 #include "base/nix/xdg_util.h" |
| 28 #include "base/synchronization/lock.h" | 29 #include "base/synchronization/lock.h" |
| 29 #include "content/public/browser/browser_thread.h" | |
| 30 #include "dbus/bus.h" | 30 #include "dbus/bus.h" |
| 31 #include "dbus/message.h" | 31 #include "dbus/message.h" |
| 32 #include "dbus/object_path.h" | 32 #include "dbus/object_path.h" |
| 33 #include "dbus/object_proxy.h" | 33 #include "dbus/object_proxy.h" |
| 34 #include "ui/gfx/x/x11_types.h" | 34 #include "ui/gfx/x/x11_types.h" |
| 35 | 35 |
| 36 namespace { | 36 namespace { |
| 37 | 37 |
| 38 enum DBusAPI { | 38 enum DBusAPI { |
| 39 NO_API, // Disable. No supported API available. | 39 NO_API, // Disable. No supported API available. |
| (...skipping 29 matching lines...) Expand all Loading... |
| 69 } // namespace | 69 } // namespace |
| 70 | 70 |
| 71 namespace content { | 71 namespace content { |
| 72 | 72 |
| 73 class PowerSaveBlockerImpl::Delegate | 73 class PowerSaveBlockerImpl::Delegate |
| 74 : public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> { | 74 : public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> { |
| 75 public: | 75 public: |
| 76 // Picks an appropriate D-Bus API to use based on the desktop environment. | 76 // Picks an appropriate D-Bus API to use based on the desktop environment. |
| 77 Delegate(PowerSaveBlockerType type, | 77 Delegate(PowerSaveBlockerType type, |
| 78 const std::string& description, | 78 const std::string& description, |
| 79 bool freedesktop_only); | 79 bool freedesktop_only, |
| 80 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, |
| 81 scoped_refptr<base::SingleThreadTaskRunner> blocking_task_runner); |
| 80 | 82 |
| 81 // Post a task to initialize the delegate on the UI thread, which will itself | 83 // Post a task to initialize the delegate on the UI thread, which will itself |
| 82 // then post a task to apply the power save block on the FILE thread. | 84 // then post a task to apply the power save block on the FILE thread. |
| 83 void Init(); | 85 void Init(); |
| 84 | 86 |
| 85 // Post a task to remove the power save block on the FILE thread, unless it | 87 // Post a task to remove the power save block on the FILE thread, unless it |
| 86 // hasn't yet been applied, in which case we just prevent it from applying. | 88 // hasn't yet been applied, in which case we just prevent it from applying. |
| 87 void CleanUp(); | 89 void CleanUp(); |
| 88 | 90 |
| 89 private: | 91 private: |
| (...skipping 16 matching lines...) Expand all Loading... |
| 106 void RemoveBlock(); | 108 void RemoveBlock(); |
| 107 | 109 |
| 108 // Asynchronous callback functions for ApplyBlock and RemoveBlock. | 110 // Asynchronous callback functions for ApplyBlock and RemoveBlock. |
| 109 // Functions do not receive ownership of |response|. | 111 // Functions do not receive ownership of |response|. |
| 110 void ApplyBlockFinished(dbus::Response* response); | 112 void ApplyBlockFinished(dbus::Response* response); |
| 111 void RemoveBlockFinished(dbus::Response* response); | 113 void RemoveBlockFinished(dbus::Response* response); |
| 112 | 114 |
| 113 // Wrapper for XScreenSaverSuspend. Checks whether the X11 Screen Saver | 115 // Wrapper for XScreenSaverSuspend. Checks whether the X11 Screen Saver |
| 114 // Extension is available first. If it isn't, this is a no-op. | 116 // Extension is available first. If it isn't, this is a no-op. |
| 115 // Must be called on the UI thread. | 117 // Must be called on the UI thread. |
| 116 static void XSSSuspendSet(bool suspend); | 118 void XSSSuspendSet(bool suspend); |
| 117 | 119 |
| 118 // If DPMS (the power saving system in X11) is not enabled, then we don't want | 120 // If DPMS (the power saving system in X11) is not enabled, then we don't want |
| 119 // to try to disable power saving, since on some desktop environments that may | 121 // to try to disable power saving, since on some desktop environments that may |
| 120 // enable DPMS with very poor default settings (e.g. turning off the display | 122 // enable DPMS with very poor default settings (e.g. turning off the display |
| 121 // after only 1 second). Must be called on the UI thread. | 123 // after only 1 second). Must be called on the UI thread. |
| 122 static bool DPMSEnabled(); | 124 bool DPMSEnabled(); |
| 123 | 125 |
| 124 // If no other method is available (i.e. not running under a Desktop | 126 // If no other method is available (i.e. not running under a Desktop |
| 125 // Environment) check whether the X11 Screen Saver Extension can be used | 127 // Environment) check whether the X11 Screen Saver Extension can be used |
| 126 // to disable the screen saver. Must be called on the UI thread. | 128 // to disable the screen saver. Must be called on the UI thread. |
| 127 static bool XSSAvailable(); | 129 bool XSSAvailable(); |
| 128 | 130 |
| 129 // Returns an appropriate D-Bus API to use based on the desktop environment. | 131 // Returns an appropriate D-Bus API to use based on the desktop environment. |
| 130 // Must be called on the UI thread, as it may call DPMSEnabled() above. | 132 // Must be called on the UI thread, as it may call DPMSEnabled() above. |
| 131 static DBusAPI SelectAPI(); | 133 DBusAPI SelectAPI(); |
| 132 | 134 |
| 133 const PowerSaveBlockerType type_; | 135 const PowerSaveBlockerType type_; |
| 134 const std::string description_; | 136 const std::string description_; |
| 135 const bool freedesktop_only_; | 137 const bool freedesktop_only_; |
| 136 | 138 |
| 137 // Initially, we post a message to the UI thread to select an API. When it | 139 // Initially, we post a message to the UI thread to select an API. When it |
| 138 // finishes, it will post a message to the FILE thread to perform the actual | 140 // finishes, it will post a message to the FILE thread to perform the actual |
| 139 // application of the block, unless enqueue_apply_ is false. We set it to | 141 // application of the block, unless enqueue_apply_ is false. We set it to |
| 140 // false when we post that message, or when RemoveBlock() is called before | 142 // false when we post that message, or when RemoveBlock() is called before |
| 141 // ApplyBlock() has run. Both api_ and enqueue_apply_ are guarded by lock_. | 143 // ApplyBlock() has run. Both api_ and enqueue_apply_ are guarded by lock_. |
| 142 DBusAPI api_; | 144 DBusAPI api_; |
| 143 bool enqueue_apply_; | 145 bool enqueue_apply_; |
| 144 base::Lock lock_; | 146 base::Lock lock_; |
| 145 | 147 |
| 146 // Indicates that a D-Bus power save blocking request is in flight. | 148 // Indicates that a D-Bus power save blocking request is in flight. |
| 147 bool block_inflight_; | 149 bool block_inflight_; |
| 148 // Used to detect erronous redundant calls to RemoveBlock(). | 150 // Used to detect erronous redundant calls to RemoveBlock(). |
| 149 bool unblock_inflight_; | 151 bool unblock_inflight_; |
| 150 // Indicates that RemoveBlock() is called before ApplyBlock() has finished. | 152 // Indicates that RemoveBlock() is called before ApplyBlock() has finished. |
| 151 // If it's true, then the RemoveBlock() call will be processed immediately | 153 // If it's true, then the RemoveBlock() call will be processed immediately |
| 152 // after ApplyBlock() has finished. | 154 // after ApplyBlock() has finished. |
| 153 bool enqueue_unblock_; | 155 bool enqueue_unblock_; |
| 154 | 156 |
| 155 scoped_refptr<dbus::Bus> bus_; | 157 scoped_refptr<dbus::Bus> bus_; |
| 156 | 158 |
| 157 // The cookie that identifies our inhibit request, | 159 // The cookie that identifies our inhibit request, |
| 158 // or 0 if there is no active inhibit request. | 160 // or 0 if there is no active inhibit request. |
| 159 uint32_t inhibit_cookie_; | 161 uint32_t inhibit_cookie_; |
| 160 | 162 |
| 163 scoped_refptr<base::SequencedTaskRunner> ui_task_runner_; |
| 164 scoped_refptr<base::SingleThreadTaskRunner> blocking_task_runner_; |
| 165 |
| 161 DISALLOW_COPY_AND_ASSIGN(Delegate); | 166 DISALLOW_COPY_AND_ASSIGN(Delegate); |
| 162 }; | 167 }; |
| 163 | 168 |
| 164 PowerSaveBlockerImpl::Delegate::Delegate(PowerSaveBlockerType type, | 169 PowerSaveBlockerImpl::Delegate::Delegate( |
| 165 const std::string& description, | 170 PowerSaveBlockerType type, |
| 166 bool freedesktop_only) | 171 const std::string& description, |
| 172 bool freedesktop_only, |
| 173 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, |
| 174 scoped_refptr<base::SingleThreadTaskRunner> blocking_task_runner) |
| 167 : type_(type), | 175 : type_(type), |
| 168 description_(description), | 176 description_(description), |
| 169 freedesktop_only_(freedesktop_only), | 177 freedesktop_only_(freedesktop_only), |
| 170 api_(NO_API), | 178 api_(NO_API), |
| 171 enqueue_apply_(false), | 179 enqueue_apply_(false), |
| 172 inhibit_cookie_(0) { | 180 inhibit_cookie_(0), |
| 181 ui_task_runner_(ui_task_runner), |
| 182 blocking_task_runner_(blocking_task_runner) { |
| 173 // We're on the client's thread here, so we don't allocate the dbus::Bus | 183 // We're on the client's thread here, so we don't allocate the dbus::Bus |
| 174 // object yet. We'll do it later in ApplyBlock(), on the FILE thread. | 184 // object yet. We'll do it later in ApplyBlock(), on the FILE thread. |
| 175 } | 185 } |
| 176 | 186 |
| 177 void PowerSaveBlockerImpl::Delegate::Init() { | 187 void PowerSaveBlockerImpl::Delegate::Init() { |
| 178 base::AutoLock lock(lock_); | 188 base::AutoLock lock(lock_); |
| 179 DCHECK(!enqueue_apply_); | 189 DCHECK(!enqueue_apply_); |
| 180 enqueue_apply_ = true; | 190 enqueue_apply_ = true; |
| 181 block_inflight_ = false; | 191 block_inflight_ = false; |
| 182 unblock_inflight_ = false; | 192 unblock_inflight_ = false; |
| 183 enqueue_unblock_ = false; | 193 enqueue_unblock_ = false; |
| 184 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 194 ui_task_runner_->PostTask(FROM_HERE, |
| 185 base::Bind(&Delegate::InitOnUIThread, this)); | 195 base::Bind(&Delegate::InitOnUIThread, this)); |
| 186 } | 196 } |
| 187 | 197 |
| 188 void PowerSaveBlockerImpl::Delegate::CleanUp() { | 198 void PowerSaveBlockerImpl::Delegate::CleanUp() { |
| 189 base::AutoLock lock(lock_); | 199 base::AutoLock lock(lock_); |
| 190 if (enqueue_apply_) { | 200 if (enqueue_apply_) { |
| 191 // If a call to ApplyBlock() has not yet been enqueued because we are still | 201 // If a call to ApplyBlock() has not yet been enqueued because we are still |
| 192 // initializing on the UI thread, then just cancel it. We don't need to | 202 // initializing on the UI thread, then just cancel it. We don't need to |
| 193 // remove the block because we haven't even applied it yet. | 203 // remove the block because we haven't even applied it yet. |
| 194 enqueue_apply_ = false; | 204 enqueue_apply_ = false; |
| 195 } else { | 205 } else { |
| 196 if (ShouldBlock()) { | 206 if (ShouldBlock()) { |
| 197 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 207 blocking_task_runner_->PostTask(FROM_HERE, |
| 198 base::Bind(&Delegate::RemoveBlock, this)); | 208 base::Bind(&Delegate::RemoveBlock, this)); |
| 199 } | 209 } |
| 200 | 210 |
| 201 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 211 ui_task_runner_->PostTask( |
| 202 base::Bind(&Delegate::XSSSuspendSet, false)); | 212 FROM_HERE, base::Bind(&Delegate::XSSSuspendSet, this, false)); |
| 203 } | 213 } |
| 204 } | 214 } |
| 205 | 215 |
| 206 void PowerSaveBlockerImpl::Delegate::InitOnUIThread() { | 216 void PowerSaveBlockerImpl::Delegate::InitOnUIThread() { |
| 207 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 217 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
| 208 base::AutoLock lock(lock_); | 218 base::AutoLock lock(lock_); |
| 209 api_ = SelectAPI(); | 219 api_ = SelectAPI(); |
| 210 | 220 |
| 211 if (enqueue_apply_) { | 221 if (enqueue_apply_) { |
| 212 if (ShouldBlock()) { | 222 if (ShouldBlock()) { |
| 213 // The thread we use here becomes the origin and D-Bus thread for the | 223 // The thread we use here becomes the origin and D-Bus thread for the |
| 214 // D-Bus library, so we need to use the same thread above for | 224 // D-Bus library, so we need to use the same thread above for |
| 215 // RemoveBlock(). It must be a thread that allows I/O operations, so we | 225 // RemoveBlock(). It must be a thread that allows I/O operations, so we |
| 216 // use the FILE thread. | 226 // use the FILE thread. |
| 217 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 227 blocking_task_runner_->PostTask(FROM_HERE, |
| 218 base::Bind(&Delegate::ApplyBlock, this)); | 228 base::Bind(&Delegate::ApplyBlock, this)); |
| 219 } | 229 } |
| 220 XSSSuspendSet(true); | 230 XSSSuspendSet(true); |
| 221 } | 231 } |
| 222 enqueue_apply_ = false; | 232 enqueue_apply_ = false; |
| 223 } | 233 } |
| 224 | 234 |
| 225 bool PowerSaveBlockerImpl::Delegate::ShouldBlock() const { | 235 bool PowerSaveBlockerImpl::Delegate::ShouldBlock() const { |
| 226 return freedesktop_only_ ? api_ == FREEDESKTOP_API : api_ != NO_API; | 236 return freedesktop_only_ ? api_ == FREEDESKTOP_API : api_ != NO_API; |
| 227 } | 237 } |
| 228 | 238 |
| 229 void PowerSaveBlockerImpl::Delegate::ApplyBlock() { | 239 void PowerSaveBlockerImpl::Delegate::ApplyBlock() { |
| 230 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 240 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
| 231 DCHECK(!bus_); // ApplyBlock() should only be called once. | 241 DCHECK(!bus_); // ApplyBlock() should only be called once. |
| 232 DCHECK(!block_inflight_); | 242 DCHECK(!block_inflight_); |
| 233 | 243 |
| 234 dbus::Bus::Options options; | 244 dbus::Bus::Options options; |
| 235 options.bus_type = dbus::Bus::SESSION; | 245 options.bus_type = dbus::Bus::SESSION; |
| 236 options.connection_type = dbus::Bus::PRIVATE; | 246 options.connection_type = dbus::Bus::PRIVATE; |
| 237 bus_ = new dbus::Bus(options); | 247 bus_ = new dbus::Bus(options); |
| 238 | 248 |
| 239 scoped_refptr<dbus::ObjectProxy> object_proxy; | 249 scoped_refptr<dbus::ObjectProxy> object_proxy; |
| 240 std::unique_ptr<dbus::MethodCall> method_call; | 250 std::unique_ptr<dbus::MethodCall> method_call; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 } | 312 } |
| 303 | 313 |
| 304 block_inflight_ = true; | 314 block_inflight_ = true; |
| 305 object_proxy->CallMethod( | 315 object_proxy->CallMethod( |
| 306 method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | 316 method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| 307 base::Bind(&PowerSaveBlockerImpl::Delegate::ApplyBlockFinished, this)); | 317 base::Bind(&PowerSaveBlockerImpl::Delegate::ApplyBlockFinished, this)); |
| 308 } | 318 } |
| 309 | 319 |
| 310 void PowerSaveBlockerImpl::Delegate::ApplyBlockFinished( | 320 void PowerSaveBlockerImpl::Delegate::ApplyBlockFinished( |
| 311 dbus::Response* response) { | 321 dbus::Response* response) { |
| 312 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 322 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
| 313 DCHECK(bus_); | 323 DCHECK(bus_); |
| 314 DCHECK(block_inflight_); | 324 DCHECK(block_inflight_); |
| 315 block_inflight_ = false; | 325 block_inflight_ = false; |
| 316 | 326 |
| 317 if (response) { | 327 if (response) { |
| 318 // The method returns an inhibit_cookie, used to uniquely identify | 328 // The method returns an inhibit_cookie, used to uniquely identify |
| 319 // this request. It should be used as an argument to Uninhibit() | 329 // this request. It should be used as an argument to Uninhibit() |
| 320 // in order to remove the request. | 330 // in order to remove the request. |
| 321 dbus::MessageReader message_reader(response); | 331 dbus::MessageReader message_reader(response); |
| 322 if (!message_reader.PopUint32(&inhibit_cookie_)) | 332 if (!message_reader.PopUint32(&inhibit_cookie_)) |
| 323 LOG(ERROR) << "Invalid Inhibit() response: " << response->ToString(); | 333 LOG(ERROR) << "Invalid Inhibit() response: " << response->ToString(); |
| 324 } else { | 334 } else { |
| 325 LOG(ERROR) << "No response to Inhibit() request!"; | 335 LOG(ERROR) << "No response to Inhibit() request!"; |
| 326 } | 336 } |
| 327 | 337 |
| 328 if (enqueue_unblock_) { | 338 if (enqueue_unblock_) { |
| 329 enqueue_unblock_ = false; | 339 enqueue_unblock_ = false; |
| 330 // RemoveBlock() was called while the Inhibit operation was in flight, | 340 // RemoveBlock() was called while the Inhibit operation was in flight, |
| 331 // so go ahead and remove the block now. | 341 // so go ahead and remove the block now. |
| 332 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 342 blocking_task_runner_->PostTask(FROM_HERE, |
| 333 base::Bind(&Delegate::RemoveBlock, this)); | 343 base::Bind(&Delegate::RemoveBlock, this)); |
| 334 } | 344 } |
| 335 } | 345 } |
| 336 | 346 |
| 337 void PowerSaveBlockerImpl::Delegate::RemoveBlock() { | 347 void PowerSaveBlockerImpl::Delegate::RemoveBlock() { |
| 338 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 348 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
| 339 DCHECK(bus_); // RemoveBlock() should only be called once. | 349 DCHECK(bus_); // RemoveBlock() should only be called once. |
| 340 DCHECK(!unblock_inflight_); | 350 DCHECK(!unblock_inflight_); |
| 341 | 351 |
| 342 if (block_inflight_) { | 352 if (block_inflight_) { |
| 343 DCHECK(!enqueue_unblock_); | 353 DCHECK(!enqueue_unblock_); |
| 344 // Can't call RemoveBlock until ApplyBlock's async operation has | 354 // Can't call RemoveBlock until ApplyBlock's async operation has |
| 345 // finished. Enqueue it for execution once ApplyBlock is done. | 355 // finished. Enqueue it for execution once ApplyBlock is done. |
| 346 enqueue_unblock_ = true; | 356 enqueue_unblock_ = true; |
| 347 return; | 357 return; |
| 348 } | 358 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 dbus::MessageWriter message_writer(method_call.get()); | 394 dbus::MessageWriter message_writer(method_call.get()); |
| 385 message_writer.AppendUint32(inhibit_cookie_); | 395 message_writer.AppendUint32(inhibit_cookie_); |
| 386 unblock_inflight_ = true; | 396 unblock_inflight_ = true; |
| 387 object_proxy->CallMethod( | 397 object_proxy->CallMethod( |
| 388 method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | 398 method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| 389 base::Bind(&PowerSaveBlockerImpl::Delegate::RemoveBlockFinished, this)); | 399 base::Bind(&PowerSaveBlockerImpl::Delegate::RemoveBlockFinished, this)); |
| 390 } | 400 } |
| 391 | 401 |
| 392 void PowerSaveBlockerImpl::Delegate::RemoveBlockFinished( | 402 void PowerSaveBlockerImpl::Delegate::RemoveBlockFinished( |
| 393 dbus::Response* response) { | 403 dbus::Response* response) { |
| 394 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 404 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
| 395 DCHECK(bus_); | 405 DCHECK(bus_); |
| 396 unblock_inflight_ = false; | 406 unblock_inflight_ = false; |
| 397 | 407 |
| 398 if (!response) | 408 if (!response) |
| 399 LOG(ERROR) << "No response to Uninhibit() request!"; | 409 LOG(ERROR) << "No response to Uninhibit() request!"; |
| 400 // We don't care about checking the result. We assume it works; we can't | 410 // We don't care about checking the result. We assume it works; we can't |
| 401 // really do anything about it anyway if it fails. | 411 // really do anything about it anyway if it fails. |
| 402 inhibit_cookie_ = 0; | 412 inhibit_cookie_ = 0; |
| 403 | 413 |
| 404 bus_->ShutdownAndBlock(); | 414 bus_->ShutdownAndBlock(); |
| 405 bus_ = nullptr; | 415 bus_ = nullptr; |
| 406 } | 416 } |
| 407 | 417 |
| 408 // static | |
| 409 void PowerSaveBlockerImpl::Delegate::XSSSuspendSet(bool suspend) { | 418 void PowerSaveBlockerImpl::Delegate::XSSSuspendSet(bool suspend) { |
| 410 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 419 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
| 411 | 420 |
| 412 if (!XSSAvailable()) | 421 if (!XSSAvailable()) |
| 413 return; | 422 return; |
| 414 | 423 |
| 415 XDisplay* display = gfx::GetXDisplay(); | 424 XDisplay* display = gfx::GetXDisplay(); |
| 416 XScreenSaverSuspend(display, suspend); | 425 XScreenSaverSuspend(display, suspend); |
| 417 } | 426 } |
| 418 | 427 |
| 419 // static | |
| 420 bool PowerSaveBlockerImpl::Delegate::DPMSEnabled() { | 428 bool PowerSaveBlockerImpl::Delegate::DPMSEnabled() { |
| 421 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 429 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
| 422 XDisplay* display = gfx::GetXDisplay(); | 430 XDisplay* display = gfx::GetXDisplay(); |
| 423 BOOL enabled = false; | 431 BOOL enabled = false; |
| 424 int dummy; | 432 int dummy; |
| 425 if (DPMSQueryExtension(display, &dummy, &dummy) && DPMSCapable(display)) { | 433 if (DPMSQueryExtension(display, &dummy, &dummy) && DPMSCapable(display)) { |
| 426 CARD16 state; | 434 CARD16 state; |
| 427 DPMSInfo(display, &state, &enabled); | 435 DPMSInfo(display, &state, &enabled); |
| 428 } | 436 } |
| 429 return enabled; | 437 return enabled; |
| 430 } | 438 } |
| 431 | 439 |
| 432 // static | |
| 433 bool PowerSaveBlockerImpl::Delegate::XSSAvailable() { | 440 bool PowerSaveBlockerImpl::Delegate::XSSAvailable() { |
| 434 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 441 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
| 435 XDisplay* display = gfx::GetXDisplay(); | 442 XDisplay* display = gfx::GetXDisplay(); |
| 436 int dummy; | 443 int dummy; |
| 437 int major; | 444 int major; |
| 438 int minor; | 445 int minor; |
| 439 | 446 |
| 440 if (!XScreenSaverQueryExtension(display, &dummy, &dummy)) | 447 if (!XScreenSaverQueryExtension(display, &dummy, &dummy)) |
| 441 return false; | 448 return false; |
| 442 | 449 |
| 443 if (!XScreenSaverQueryVersion(display, &major, &minor)) | 450 if (!XScreenSaverQueryVersion(display, &major, &minor)) |
| 444 return false; | 451 return false; |
| 445 | 452 |
| 446 return major > 1 || (major == 1 && minor >= 1); | 453 return major > 1 || (major == 1 && minor >= 1); |
| 447 } | 454 } |
| 448 | 455 |
| 449 // static | |
| 450 DBusAPI PowerSaveBlockerImpl::Delegate::SelectAPI() { | 456 DBusAPI PowerSaveBlockerImpl::Delegate::SelectAPI() { |
| 451 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 457 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
| 452 std::unique_ptr<base::Environment> env(base::Environment::Create()); | 458 std::unique_ptr<base::Environment> env(base::Environment::Create()); |
| 453 switch (base::nix::GetDesktopEnvironment(env.get())) { | 459 switch (base::nix::GetDesktopEnvironment(env.get())) { |
| 454 case base::nix::DESKTOP_ENVIRONMENT_GNOME: | 460 case base::nix::DESKTOP_ENVIRONMENT_GNOME: |
| 455 case base::nix::DESKTOP_ENVIRONMENT_UNITY: | 461 case base::nix::DESKTOP_ENVIRONMENT_UNITY: |
| 456 if (DPMSEnabled()) | 462 if (DPMSEnabled()) |
| 457 return GNOME_API; | 463 return GNOME_API; |
| 458 break; | 464 break; |
| 459 case base::nix::DESKTOP_ENVIRONMENT_XFCE: | 465 case base::nix::DESKTOP_ENVIRONMENT_XFCE: |
| 460 case base::nix::DESKTOP_ENVIRONMENT_KDE4: | 466 case base::nix::DESKTOP_ENVIRONMENT_KDE4: |
| 461 case base::nix::DESKTOP_ENVIRONMENT_KDE5: | 467 case base::nix::DESKTOP_ENVIRONMENT_KDE5: |
| 462 if (DPMSEnabled()) | 468 if (DPMSEnabled()) |
| 463 return FREEDESKTOP_API; | 469 return FREEDESKTOP_API; |
| 464 break; | 470 break; |
| 465 case base::nix::DESKTOP_ENVIRONMENT_KDE3: | 471 case base::nix::DESKTOP_ENVIRONMENT_KDE3: |
| 466 case base::nix::DESKTOP_ENVIRONMENT_OTHER: | 472 case base::nix::DESKTOP_ENVIRONMENT_OTHER: |
| 467 // Not supported. | 473 // Not supported. |
| 468 break; | 474 break; |
| 469 } | 475 } |
| 470 return NO_API; | 476 return NO_API; |
| 471 } | 477 } |
| 472 | 478 |
| 473 PowerSaveBlockerImpl::PowerSaveBlockerImpl(PowerSaveBlockerType type, | 479 PowerSaveBlockerImpl::PowerSaveBlockerImpl( |
| 474 Reason reason, | 480 PowerSaveBlockerType type, |
| 475 const std::string& description) | 481 Reason reason, |
| 476 : delegate_(new Delegate(type, description, false /* freedesktop_only */)) { | 482 const std::string& description, |
| 483 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, |
| 484 scoped_refptr<base::SingleThreadTaskRunner> blocking_task_runner) |
| 485 : delegate_(new Delegate(type, |
| 486 description, |
| 487 false /* freedesktop_only */, |
| 488 ui_task_runner, |
| 489 blocking_task_runner)), |
| 490 ui_task_runner_(ui_task_runner), |
| 491 blocking_task_runner_(blocking_task_runner) { |
| 477 delegate_->Init(); | 492 delegate_->Init(); |
| 478 | 493 |
| 479 if (type == kPowerSaveBlockPreventDisplaySleep) { | 494 if (type == kPowerSaveBlockPreventDisplaySleep) { |
| 480 freedesktop_suspend_delegate_ = | 495 freedesktop_suspend_delegate_ = new Delegate( |
| 481 new Delegate(kPowerSaveBlockPreventAppSuspension, description, | 496 kPowerSaveBlockPreventAppSuspension, description, |
| 482 true /* freedesktop_only */); | 497 true /* freedesktop_only */, ui_task_runner, blocking_task_runner); |
| 483 freedesktop_suspend_delegate_->Init(); | 498 freedesktop_suspend_delegate_->Init(); |
| 484 } | 499 } |
| 485 } | 500 } |
| 486 | 501 |
| 487 PowerSaveBlockerImpl::~PowerSaveBlockerImpl() { | 502 PowerSaveBlockerImpl::~PowerSaveBlockerImpl() { |
| 488 delegate_->CleanUp(); | 503 delegate_->CleanUp(); |
| 489 if (freedesktop_suspend_delegate_) | 504 if (freedesktop_suspend_delegate_) |
| 490 freedesktop_suspend_delegate_->CleanUp(); | 505 freedesktop_suspend_delegate_->CleanUp(); |
| 491 } | 506 } |
| 492 | 507 |
| 493 } // namespace content | 508 } // namespace content |
| OLD | NEW |