| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <X11/Xlib.h> | |
| 6 #include <X11/extensions/dpms.h> | |
| 7 #include <X11/extensions/scrnsaver.h> | |
| 8 #include <stdint.h> | |
| 9 | |
| 10 #include <memory> | |
| 11 | |
| 12 #include "device/power_save_blocker/power_save_blocker_impl.h" | |
| 13 // Xlib #defines Status, but we can't have that for some of our headers. | |
| 14 #ifdef Status | |
| 15 #undef Status | |
| 16 #endif | |
| 17 | |
| 18 #include "base/bind.h" | |
| 19 #include "base/callback.h" | |
| 20 #include "base/command_line.h" | |
| 21 #include "base/environment.h" | |
| 22 #include "base/files/file_path.h" | |
| 23 #include "base/location.h" | |
| 24 #include "base/logging.h" | |
| 25 #include "base/macros.h" | |
| 26 #include "base/memory/ref_counted.h" | |
| 27 #include "base/memory/singleton.h" | |
| 28 #include "base/nix/xdg_util.h" | |
| 29 #include "base/synchronization/lock.h" | |
| 30 #include "dbus/bus.h" | |
| 31 #include "dbus/message.h" | |
| 32 #include "dbus/object_path.h" | |
| 33 #include "dbus/object_proxy.h" | |
| 34 #include "ui/gfx/x/x11_types.h" | |
| 35 | |
| 36 namespace { | |
| 37 | |
| 38 enum DBusAPI { | |
| 39 NO_API, // Disable. No supported API available. | |
| 40 GNOME_API, // Use the GNOME API. (Supports more features.) | |
| 41 FREEDESKTOP_API, // Use the FreeDesktop API, for KDE4, KDE5, and XFCE. | |
| 42 }; | |
| 43 | |
| 44 // Inhibit flags defined in the org.gnome.SessionManager interface. | |
| 45 // Can be OR'd together and passed as argument to the Inhibit() method | |
| 46 // to specify which power management features we want to suspend. | |
| 47 enum GnomeAPIInhibitFlags { | |
| 48 INHIBIT_LOGOUT = 1, | |
| 49 INHIBIT_SWITCH_USER = 2, | |
| 50 INHIBIT_SUSPEND_SESSION = 4, | |
| 51 INHIBIT_MARK_SESSION_IDLE = 8 | |
| 52 }; | |
| 53 | |
| 54 const char kGnomeAPIServiceName[] = "org.gnome.SessionManager"; | |
| 55 const char kGnomeAPIInterfaceName[] = "org.gnome.SessionManager"; | |
| 56 const char kGnomeAPIObjectPath[] = "/org/gnome/SessionManager"; | |
| 57 | |
| 58 const char kFreeDesktopAPIPowerServiceName[] = | |
| 59 "org.freedesktop.PowerManagement"; | |
| 60 const char kFreeDesktopAPIPowerInterfaceName[] = | |
| 61 "org.freedesktop.PowerManagement.Inhibit"; | |
| 62 const char kFreeDesktopAPIPowerObjectPath[] = | |
| 63 "/org/freedesktop/PowerManagement/Inhibit"; | |
| 64 | |
| 65 const char kFreeDesktopAPIScreenServiceName[] = "org.freedesktop.ScreenSaver"; | |
| 66 const char kFreeDesktopAPIScreenInterfaceName[] = "org.freedesktop.ScreenSaver"; | |
| 67 const char kFreeDesktopAPIScreenObjectPath[] = "/org/freedesktop/ScreenSaver"; | |
| 68 | |
| 69 } // namespace | |
| 70 | |
| 71 namespace device { | |
| 72 | |
| 73 class PowerSaveBlockerImpl::Delegate | |
| 74 : public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> { | |
| 75 public: | |
| 76 // Picks an appropriate D-Bus API to use based on the desktop environment. | |
| 77 Delegate(PowerSaveBlockerType type, | |
| 78 const std::string& description, | |
| 79 bool freedesktop_only, | |
| 80 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, | |
| 81 scoped_refptr<base::SingleThreadTaskRunner> blocking_task_runner); | |
| 82 | |
| 83 // Post a task to initialize the delegate on the UI thread, which will itself | |
| 84 // then post a task to apply the power save block on the FILE thread. | |
| 85 void Init(); | |
| 86 | |
| 87 // Post a task to remove the power save block on the FILE thread, unless it | |
| 88 // hasn't yet been applied, in which case we just prevent it from applying. | |
| 89 void CleanUp(); | |
| 90 | |
| 91 private: | |
| 92 friend class base::RefCountedThreadSafe<Delegate>; | |
| 93 ~Delegate() {} | |
| 94 | |
| 95 // Selects an appropriate D-Bus API to use for this object. Must be called on | |
| 96 // the UI thread. Checks enqueue_apply_ once an API has been selected, and | |
| 97 // enqueues a call back to ApplyBlock() if it is true. See the comments for | |
| 98 // enqueue_apply_ below. | |
| 99 void InitOnUIThread(); | |
| 100 | |
| 101 // Returns true if ApplyBlock() / RemoveBlock() should be called. | |
| 102 bool ShouldBlock() const; | |
| 103 | |
| 104 // Apply or remove the power save block, respectively. These methods should be | |
| 105 // called once each, on the same thread, per instance. They block waiting for | |
| 106 // the action to complete (with a timeout); the thread must thus allow I/O. | |
| 107 void ApplyBlock(); | |
| 108 void RemoveBlock(); | |
| 109 | |
| 110 // Asynchronous callback functions for ApplyBlock and RemoveBlock. | |
| 111 // Functions do not receive ownership of |response|. | |
| 112 void ApplyBlockFinished(dbus::Response* response); | |
| 113 void RemoveBlockFinished(dbus::Response* response); | |
| 114 | |
| 115 // Wrapper for XScreenSaverSuspend. Checks whether the X11 Screen Saver | |
| 116 // Extension is available first. If it isn't, this is a no-op. | |
| 117 // Must be called on the UI thread. | |
| 118 void XSSSuspendSet(bool suspend); | |
| 119 | |
| 120 // If DPMS (the power saving system in X11) is not enabled, then we don't want | |
| 121 // to try to disable power saving, since on some desktop environments that may | |
| 122 // enable DPMS with very poor default settings (e.g. turning off the display | |
| 123 // after only 1 second). Must be called on the UI thread. | |
| 124 bool DPMSEnabled(); | |
| 125 | |
| 126 // If no other method is available (i.e. not running under a Desktop | |
| 127 // Environment) check whether the X11 Screen Saver Extension can be used | |
| 128 // to disable the screen saver. Must be called on the UI thread. | |
| 129 bool XSSAvailable(); | |
| 130 | |
| 131 // Returns an appropriate D-Bus API to use based on the desktop environment. | |
| 132 // Must be called on the UI thread, as it may call DPMSEnabled() above. | |
| 133 DBusAPI SelectAPI(); | |
| 134 | |
| 135 const PowerSaveBlockerType type_; | |
| 136 const std::string description_; | |
| 137 const bool freedesktop_only_; | |
| 138 | |
| 139 // Initially, we post a message to the UI thread to select an API. When it | |
| 140 // finishes, it will post a message to the FILE thread to perform the actual | |
| 141 // application of the block, unless enqueue_apply_ is false. We set it to | |
| 142 // false when we post that message, or when RemoveBlock() is called before | |
| 143 // ApplyBlock() has run. Both api_ and enqueue_apply_ are guarded by lock_. | |
| 144 DBusAPI api_; | |
| 145 bool enqueue_apply_; | |
| 146 base::Lock lock_; | |
| 147 | |
| 148 // Indicates that a D-Bus power save blocking request is in flight. | |
| 149 bool block_inflight_; | |
| 150 // Used to detect erronous redundant calls to RemoveBlock(). | |
| 151 bool unblock_inflight_; | |
| 152 // Indicates that RemoveBlock() is called before ApplyBlock() has finished. | |
| 153 // If it's true, then the RemoveBlock() call will be processed immediately | |
| 154 // after ApplyBlock() has finished. | |
| 155 bool enqueue_unblock_; | |
| 156 | |
| 157 scoped_refptr<dbus::Bus> bus_; | |
| 158 | |
| 159 // The cookie that identifies our inhibit request, | |
| 160 // or 0 if there is no active inhibit request. | |
| 161 uint32_t inhibit_cookie_; | |
| 162 | |
| 163 scoped_refptr<base::SequencedTaskRunner> ui_task_runner_; | |
| 164 scoped_refptr<base::SingleThreadTaskRunner> blocking_task_runner_; | |
| 165 | |
| 166 DISALLOW_COPY_AND_ASSIGN(Delegate); | |
| 167 }; | |
| 168 | |
| 169 PowerSaveBlockerImpl::Delegate::Delegate( | |
| 170 PowerSaveBlockerType type, | |
| 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) | |
| 175 : type_(type), | |
| 176 description_(description), | |
| 177 freedesktop_only_(freedesktop_only), | |
| 178 api_(NO_API), | |
| 179 enqueue_apply_(false), | |
| 180 inhibit_cookie_(0), | |
| 181 ui_task_runner_(ui_task_runner), | |
| 182 blocking_task_runner_(blocking_task_runner) { | |
| 183 // We're on the client's thread here, so we don't allocate the dbus::Bus | |
| 184 // object yet. We'll do it later in ApplyBlock(), on the FILE thread. | |
| 185 } | |
| 186 | |
| 187 void PowerSaveBlockerImpl::Delegate::Init() { | |
| 188 base::AutoLock lock(lock_); | |
| 189 DCHECK(!enqueue_apply_); | |
| 190 enqueue_apply_ = true; | |
| 191 block_inflight_ = false; | |
| 192 unblock_inflight_ = false; | |
| 193 enqueue_unblock_ = false; | |
| 194 ui_task_runner_->PostTask(FROM_HERE, | |
| 195 base::Bind(&Delegate::InitOnUIThread, this)); | |
| 196 } | |
| 197 | |
| 198 void PowerSaveBlockerImpl::Delegate::CleanUp() { | |
| 199 base::AutoLock lock(lock_); | |
| 200 if (enqueue_apply_) { | |
| 201 // If a call to ApplyBlock() has not yet been enqueued because we are still | |
| 202 // initializing on the UI thread, then just cancel it. We don't need to | |
| 203 // remove the block because we haven't even applied it yet. | |
| 204 enqueue_apply_ = false; | |
| 205 } else { | |
| 206 if (ShouldBlock()) { | |
| 207 blocking_task_runner_->PostTask(FROM_HERE, | |
| 208 base::Bind(&Delegate::RemoveBlock, this)); | |
| 209 } | |
| 210 | |
| 211 ui_task_runner_->PostTask( | |
| 212 FROM_HERE, base::Bind(&Delegate::XSSSuspendSet, this, false)); | |
| 213 } | |
| 214 } | |
| 215 | |
| 216 void PowerSaveBlockerImpl::Delegate::InitOnUIThread() { | |
| 217 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | |
| 218 base::AutoLock lock(lock_); | |
| 219 api_ = SelectAPI(); | |
| 220 | |
| 221 if (enqueue_apply_) { | |
| 222 if (ShouldBlock()) { | |
| 223 // The thread we use here becomes the origin and D-Bus thread for the | |
| 224 // D-Bus library, so we need to use the same thread above for | |
| 225 // RemoveBlock(). It must be a thread that allows I/O operations, so we | |
| 226 // use the FILE thread. | |
| 227 blocking_task_runner_->PostTask(FROM_HERE, | |
| 228 base::Bind(&Delegate::ApplyBlock, this)); | |
| 229 } | |
| 230 XSSSuspendSet(true); | |
| 231 } | |
| 232 enqueue_apply_ = false; | |
| 233 } | |
| 234 | |
| 235 bool PowerSaveBlockerImpl::Delegate::ShouldBlock() const { | |
| 236 return freedesktop_only_ ? api_ == FREEDESKTOP_API : api_ != NO_API; | |
| 237 } | |
| 238 | |
| 239 void PowerSaveBlockerImpl::Delegate::ApplyBlock() { | |
| 240 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | |
| 241 DCHECK(!bus_); // ApplyBlock() should only be called once. | |
| 242 DCHECK(!block_inflight_); | |
| 243 | |
| 244 dbus::Bus::Options options; | |
| 245 options.bus_type = dbus::Bus::SESSION; | |
| 246 options.connection_type = dbus::Bus::PRIVATE; | |
| 247 bus_ = new dbus::Bus(options); | |
| 248 | |
| 249 scoped_refptr<dbus::ObjectProxy> object_proxy; | |
| 250 std::unique_ptr<dbus::MethodCall> method_call; | |
| 251 std::unique_ptr<dbus::MessageWriter> message_writer; | |
| 252 | |
| 253 switch (api_) { | |
| 254 case NO_API: | |
| 255 NOTREACHED(); // We should never call this method with this value. | |
| 256 return; | |
| 257 case GNOME_API: | |
| 258 object_proxy = bus_->GetObjectProxy( | |
| 259 kGnomeAPIServiceName, dbus::ObjectPath(kGnomeAPIObjectPath)); | |
| 260 method_call.reset( | |
| 261 new dbus::MethodCall(kGnomeAPIInterfaceName, "Inhibit")); | |
| 262 message_writer.reset(new dbus::MessageWriter(method_call.get())); | |
| 263 // The arguments of the method are: | |
| 264 // app_id: The application identifier | |
| 265 // toplevel_xid: The toplevel X window identifier | |
| 266 // reason: The reason for the inhibit | |
| 267 // flags: Flags that spefify what should be inhibited | |
| 268 message_writer->AppendString( | |
| 269 base::CommandLine::ForCurrentProcess()->GetProgram().value()); | |
| 270 message_writer->AppendUint32(0); // should be toplevel_xid | |
| 271 message_writer->AppendString(description_); | |
| 272 { | |
| 273 uint32_t flags = 0; | |
| 274 switch (type_) { | |
| 275 case kPowerSaveBlockPreventDisplaySleep: | |
| 276 flags |= INHIBIT_MARK_SESSION_IDLE; | |
| 277 flags |= INHIBIT_SUSPEND_SESSION; | |
| 278 break; | |
| 279 case kPowerSaveBlockPreventAppSuspension: | |
| 280 flags |= INHIBIT_SUSPEND_SESSION; | |
| 281 break; | |
| 282 } | |
| 283 message_writer->AppendUint32(flags); | |
| 284 } | |
| 285 break; | |
| 286 case FREEDESKTOP_API: | |
| 287 switch (type_) { | |
| 288 case kPowerSaveBlockPreventDisplaySleep: | |
| 289 object_proxy = bus_->GetObjectProxy( | |
| 290 kFreeDesktopAPIScreenServiceName, | |
| 291 dbus::ObjectPath(kFreeDesktopAPIScreenObjectPath)); | |
| 292 method_call.reset(new dbus::MethodCall( | |
| 293 kFreeDesktopAPIScreenInterfaceName, "Inhibit")); | |
| 294 break; | |
| 295 case kPowerSaveBlockPreventAppSuspension: | |
| 296 object_proxy = bus_->GetObjectProxy( | |
| 297 kFreeDesktopAPIPowerServiceName, | |
| 298 dbus::ObjectPath(kFreeDesktopAPIPowerObjectPath)); | |
| 299 method_call.reset(new dbus::MethodCall( | |
| 300 kFreeDesktopAPIPowerInterfaceName, "Inhibit")); | |
| 301 break; | |
| 302 } | |
| 303 message_writer.reset(new dbus::MessageWriter(method_call.get())); | |
| 304 // The arguments of the method are: | |
| 305 // app_id: The application identifier | |
| 306 // reason: The reason for the inhibit | |
| 307 message_writer->AppendString( | |
| 308 base::CommandLine::ForCurrentProcess()->GetProgram().value()); | |
| 309 message_writer->AppendString(description_); | |
| 310 break; | |
| 311 } | |
| 312 | |
| 313 block_inflight_ = true; | |
| 314 object_proxy->CallMethod( | |
| 315 method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | |
| 316 base::Bind(&PowerSaveBlockerImpl::Delegate::ApplyBlockFinished, this)); | |
| 317 } | |
| 318 | |
| 319 void PowerSaveBlockerImpl::Delegate::ApplyBlockFinished( | |
| 320 dbus::Response* response) { | |
| 321 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | |
| 322 DCHECK(bus_); | |
| 323 DCHECK(block_inflight_); | |
| 324 block_inflight_ = false; | |
| 325 | |
| 326 if (response) { | |
| 327 // The method returns an inhibit_cookie, used to uniquely identify | |
| 328 // this request. It should be used as an argument to Uninhibit() | |
| 329 // in order to remove the request. | |
| 330 dbus::MessageReader message_reader(response); | |
| 331 if (!message_reader.PopUint32(&inhibit_cookie_)) | |
| 332 LOG(ERROR) << "Invalid Inhibit() response: " << response->ToString(); | |
| 333 } else { | |
| 334 LOG(ERROR) << "No response to Inhibit() request!"; | |
| 335 } | |
| 336 | |
| 337 if (enqueue_unblock_) { | |
| 338 enqueue_unblock_ = false; | |
| 339 // RemoveBlock() was called while the Inhibit operation was in flight, | |
| 340 // so go ahead and remove the block now. | |
| 341 blocking_task_runner_->PostTask(FROM_HERE, | |
| 342 base::Bind(&Delegate::RemoveBlock, this)); | |
| 343 } | |
| 344 } | |
| 345 | |
| 346 void PowerSaveBlockerImpl::Delegate::RemoveBlock() { | |
| 347 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | |
| 348 DCHECK(bus_); // RemoveBlock() should only be called once. | |
| 349 DCHECK(!unblock_inflight_); | |
| 350 | |
| 351 if (block_inflight_) { | |
| 352 DCHECK(!enqueue_unblock_); | |
| 353 // Can't call RemoveBlock until ApplyBlock's async operation has | |
| 354 // finished. Enqueue it for execution once ApplyBlock is done. | |
| 355 enqueue_unblock_ = true; | |
| 356 return; | |
| 357 } | |
| 358 | |
| 359 scoped_refptr<dbus::ObjectProxy> object_proxy; | |
| 360 std::unique_ptr<dbus::MethodCall> method_call; | |
| 361 | |
| 362 switch (api_) { | |
| 363 case NO_API: | |
| 364 NOTREACHED(); // We should never call this method with this value. | |
| 365 return; | |
| 366 case GNOME_API: | |
| 367 object_proxy = bus_->GetObjectProxy( | |
| 368 kGnomeAPIServiceName, dbus::ObjectPath(kGnomeAPIObjectPath)); | |
| 369 method_call.reset( | |
| 370 new dbus::MethodCall(kGnomeAPIInterfaceName, "Uninhibit")); | |
| 371 break; | |
| 372 case FREEDESKTOP_API: | |
| 373 switch (type_) { | |
| 374 case kPowerSaveBlockPreventDisplaySleep: | |
| 375 object_proxy = bus_->GetObjectProxy( | |
| 376 kFreeDesktopAPIScreenServiceName, | |
| 377 dbus::ObjectPath(kFreeDesktopAPIScreenObjectPath)); | |
| 378 method_call.reset(new dbus::MethodCall( | |
| 379 kFreeDesktopAPIScreenInterfaceName, "UnInhibit")); | |
| 380 break; | |
| 381 case kPowerSaveBlockPreventAppSuspension: | |
| 382 object_proxy = bus_->GetObjectProxy( | |
| 383 kFreeDesktopAPIPowerServiceName, | |
| 384 dbus::ObjectPath(kFreeDesktopAPIPowerObjectPath)); | |
| 385 method_call.reset(new dbus::MethodCall( | |
| 386 kFreeDesktopAPIPowerInterfaceName, "UnInhibit")); | |
| 387 break; | |
| 388 } | |
| 389 break; | |
| 390 } | |
| 391 | |
| 392 dbus::MessageWriter message_writer(method_call.get()); | |
| 393 message_writer.AppendUint32(inhibit_cookie_); | |
| 394 unblock_inflight_ = true; | |
| 395 object_proxy->CallMethod( | |
| 396 method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | |
| 397 base::Bind(&PowerSaveBlockerImpl::Delegate::RemoveBlockFinished, this)); | |
| 398 } | |
| 399 | |
| 400 void PowerSaveBlockerImpl::Delegate::RemoveBlockFinished( | |
| 401 dbus::Response* response) { | |
| 402 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | |
| 403 DCHECK(bus_); | |
| 404 unblock_inflight_ = false; | |
| 405 | |
| 406 if (!response) | |
| 407 LOG(ERROR) << "No response to Uninhibit() request!"; | |
| 408 // We don't care about checking the result. We assume it works; we can't | |
| 409 // really do anything about it anyway if it fails. | |
| 410 inhibit_cookie_ = 0; | |
| 411 | |
| 412 bus_->ShutdownAndBlock(); | |
| 413 bus_ = nullptr; | |
| 414 } | |
| 415 | |
| 416 void PowerSaveBlockerImpl::Delegate::XSSSuspendSet(bool suspend) { | |
| 417 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | |
| 418 | |
| 419 if (!XSSAvailable()) | |
| 420 return; | |
| 421 | |
| 422 XDisplay* display = gfx::GetXDisplay(); | |
| 423 XScreenSaverSuspend(display, suspend); | |
| 424 } | |
| 425 | |
| 426 bool PowerSaveBlockerImpl::Delegate::DPMSEnabled() { | |
| 427 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | |
| 428 XDisplay* display = gfx::GetXDisplay(); | |
| 429 BOOL enabled = false; | |
| 430 int dummy; | |
| 431 if (DPMSQueryExtension(display, &dummy, &dummy) && DPMSCapable(display)) { | |
| 432 CARD16 state; | |
| 433 DPMSInfo(display, &state, &enabled); | |
| 434 } | |
| 435 return enabled; | |
| 436 } | |
| 437 | |
| 438 bool PowerSaveBlockerImpl::Delegate::XSSAvailable() { | |
| 439 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | |
| 440 XDisplay* display = gfx::GetXDisplay(); | |
| 441 int dummy; | |
| 442 int major; | |
| 443 int minor; | |
| 444 | |
| 445 if (!XScreenSaverQueryExtension(display, &dummy, &dummy)) | |
| 446 return false; | |
| 447 | |
| 448 if (!XScreenSaverQueryVersion(display, &major, &minor)) | |
| 449 return false; | |
| 450 | |
| 451 return major > 1 || (major == 1 && minor >= 1); | |
| 452 } | |
| 453 | |
| 454 DBusAPI PowerSaveBlockerImpl::Delegate::SelectAPI() { | |
| 455 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | |
| 456 std::unique_ptr<base::Environment> env(base::Environment::Create()); | |
| 457 switch (base::nix::GetDesktopEnvironment(env.get())) { | |
| 458 case base::nix::DESKTOP_ENVIRONMENT_GNOME: | |
| 459 case base::nix::DESKTOP_ENVIRONMENT_UNITY: | |
| 460 if (DPMSEnabled()) | |
| 461 return GNOME_API; | |
| 462 break; | |
| 463 case base::nix::DESKTOP_ENVIRONMENT_XFCE: | |
| 464 case base::nix::DESKTOP_ENVIRONMENT_KDE4: | |
| 465 case base::nix::DESKTOP_ENVIRONMENT_KDE5: | |
| 466 if (DPMSEnabled()) | |
| 467 return FREEDESKTOP_API; | |
| 468 break; | |
| 469 case base::nix::DESKTOP_ENVIRONMENT_KDE3: | |
| 470 case base::nix::DESKTOP_ENVIRONMENT_OTHER: | |
| 471 // Not supported. | |
| 472 break; | |
| 473 } | |
| 474 return NO_API; | |
| 475 } | |
| 476 | |
| 477 PowerSaveBlockerImpl::PowerSaveBlockerImpl( | |
| 478 PowerSaveBlockerType type, | |
| 479 Reason reason, | |
| 480 const std::string& description, | |
| 481 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, | |
| 482 scoped_refptr<base::SingleThreadTaskRunner> blocking_task_runner) | |
| 483 : delegate_(new Delegate(type, | |
| 484 description, | |
| 485 false /* freedesktop_only */, | |
| 486 ui_task_runner, | |
| 487 blocking_task_runner)), | |
| 488 ui_task_runner_(ui_task_runner), | |
| 489 blocking_task_runner_(blocking_task_runner) { | |
| 490 delegate_->Init(); | |
| 491 | |
| 492 if (type == kPowerSaveBlockPreventDisplaySleep) { | |
| 493 freedesktop_suspend_delegate_ = new Delegate( | |
| 494 kPowerSaveBlockPreventAppSuspension, description, | |
| 495 true /* freedesktop_only */, ui_task_runner, blocking_task_runner); | |
| 496 freedesktop_suspend_delegate_->Init(); | |
| 497 } | |
| 498 } | |
| 499 | |
| 500 PowerSaveBlockerImpl::~PowerSaveBlockerImpl() { | |
| 501 delegate_->CleanUp(); | |
| 502 if (freedesktop_suspend_delegate_) | |
| 503 freedesktop_suspend_delegate_->CleanUp(); | |
| 504 } | |
| 505 | |
| 506 } // namespace device | |
| OLD | NEW |