| 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> |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 blocking_task_runner_->PostTask(FROM_HERE, | 210 blocking_task_runner_->PostTask(FROM_HERE, |
| 211 base::Bind(&Delegate::RemoveBlock, this)); | 211 base::Bind(&Delegate::RemoveBlock, this)); |
| 212 } | 212 } |
| 213 | 213 |
| 214 ui_task_runner_->PostTask( | 214 ui_task_runner_->PostTask( |
| 215 FROM_HERE, base::Bind(&Delegate::XSSSuspendSet, this, false)); | 215 FROM_HERE, base::Bind(&Delegate::XSSSuspendSet, this, false)); |
| 216 } | 216 } |
| 217 } | 217 } |
| 218 | 218 |
| 219 void PowerSaveBlocker::Delegate::InitOnUIThread() { | 219 void PowerSaveBlocker::Delegate::InitOnUIThread() { |
| 220 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | 220 DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); |
| 221 base::AutoLock lock(lock_); | 221 base::AutoLock lock(lock_); |
| 222 api_ = SelectAPI(); | 222 api_ = SelectAPI(); |
| 223 | 223 |
| 224 if (enqueue_apply_) { | 224 if (enqueue_apply_) { |
| 225 if (ShouldBlock()) { | 225 if (ShouldBlock()) { |
| 226 // The thread we use here becomes the origin and D-Bus thread for the | 226 // The thread we use here becomes the origin and D-Bus thread for the |
| 227 // D-Bus library, so we need to use the same thread above for | 227 // D-Bus library, so we need to use the same thread above for |
| 228 // RemoveBlock(). It must be a thread that allows I/O operations, so we | 228 // RemoveBlock(). It must be a thread that allows I/O operations, so we |
| 229 // use the FILE thread. | 229 // use the FILE thread. |
| 230 blocking_task_runner_->PostTask(FROM_HERE, | 230 blocking_task_runner_->PostTask(FROM_HERE, |
| 231 base::Bind(&Delegate::ApplyBlock, this)); | 231 base::Bind(&Delegate::ApplyBlock, this)); |
| 232 } | 232 } |
| 233 XSSSuspendSet(true); | 233 XSSSuspendSet(true); |
| 234 } | 234 } |
| 235 enqueue_apply_ = false; | 235 enqueue_apply_ = false; |
| 236 } | 236 } |
| 237 | 237 |
| 238 bool PowerSaveBlocker::Delegate::ShouldBlock() const { | 238 bool PowerSaveBlocker::Delegate::ShouldBlock() const { |
| 239 return freedesktop_only_ ? api_ == FREEDESKTOP_API : api_ != NO_API; | 239 return freedesktop_only_ ? api_ == FREEDESKTOP_API : api_ != NO_API; |
| 240 } | 240 } |
| 241 | 241 |
| 242 void PowerSaveBlocker::Delegate::ApplyBlock() { | 242 void PowerSaveBlocker::Delegate::ApplyBlock() { |
| 243 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | 243 DCHECK(blocking_task_runner_->RunsTasksInCurrentSequence()); |
| 244 DCHECK(!bus_); // ApplyBlock() should only be called once. | 244 DCHECK(!bus_); // ApplyBlock() should only be called once. |
| 245 DCHECK(!block_inflight_); | 245 DCHECK(!block_inflight_); |
| 246 | 246 |
| 247 dbus::Bus::Options options; | 247 dbus::Bus::Options options; |
| 248 options.bus_type = dbus::Bus::SESSION; | 248 options.bus_type = dbus::Bus::SESSION; |
| 249 options.connection_type = dbus::Bus::PRIVATE; | 249 options.connection_type = dbus::Bus::PRIVATE; |
| 250 bus_ = new dbus::Bus(options); | 250 bus_ = new dbus::Bus(options); |
| 251 | 251 |
| 252 scoped_refptr<dbus::ObjectProxy> object_proxy; | 252 scoped_refptr<dbus::ObjectProxy> object_proxy; |
| 253 std::unique_ptr<dbus::MethodCall> method_call; | 253 std::unique_ptr<dbus::MethodCall> method_call; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 break; | 313 break; |
| 314 } | 314 } |
| 315 | 315 |
| 316 block_inflight_ = true; | 316 block_inflight_ = true; |
| 317 object_proxy->CallMethod( | 317 object_proxy->CallMethod( |
| 318 method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | 318 method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| 319 base::Bind(&PowerSaveBlocker::Delegate::ApplyBlockFinished, this)); | 319 base::Bind(&PowerSaveBlocker::Delegate::ApplyBlockFinished, this)); |
| 320 } | 320 } |
| 321 | 321 |
| 322 void PowerSaveBlocker::Delegate::ApplyBlockFinished(dbus::Response* response) { | 322 void PowerSaveBlocker::Delegate::ApplyBlockFinished(dbus::Response* response) { |
| 323 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | 323 DCHECK(blocking_task_runner_->RunsTasksInCurrentSequence()); |
| 324 DCHECK(bus_); | 324 DCHECK(bus_); |
| 325 DCHECK(block_inflight_); | 325 DCHECK(block_inflight_); |
| 326 block_inflight_ = false; | 326 block_inflight_ = false; |
| 327 | 327 |
| 328 if (response) { | 328 if (response) { |
| 329 // The method returns an inhibit_cookie, used to uniquely identify | 329 // The method returns an inhibit_cookie, used to uniquely identify |
| 330 // this request. It should be used as an argument to Uninhibit() | 330 // this request. It should be used as an argument to Uninhibit() |
| 331 // in order to remove the request. | 331 // in order to remove the request. |
| 332 dbus::MessageReader message_reader(response); | 332 dbus::MessageReader message_reader(response); |
| 333 if (!message_reader.PopUint32(&inhibit_cookie_)) | 333 if (!message_reader.PopUint32(&inhibit_cookie_)) |
| 334 LOG(ERROR) << "Invalid Inhibit() response: " << response->ToString(); | 334 LOG(ERROR) << "Invalid Inhibit() response: " << response->ToString(); |
| 335 } else { | 335 } else { |
| 336 LOG(ERROR) << "No response to Inhibit() request!"; | 336 LOG(ERROR) << "No response to Inhibit() request!"; |
| 337 } | 337 } |
| 338 | 338 |
| 339 if (enqueue_unblock_) { | 339 if (enqueue_unblock_) { |
| 340 enqueue_unblock_ = false; | 340 enqueue_unblock_ = false; |
| 341 // RemoveBlock() was called while the Inhibit operation was in flight, | 341 // RemoveBlock() was called while the Inhibit operation was in flight, |
| 342 // so go ahead and remove the block now. | 342 // so go ahead and remove the block now. |
| 343 blocking_task_runner_->PostTask(FROM_HERE, | 343 blocking_task_runner_->PostTask(FROM_HERE, |
| 344 base::Bind(&Delegate::RemoveBlock, this)); | 344 base::Bind(&Delegate::RemoveBlock, this)); |
| 345 } | 345 } |
| 346 } | 346 } |
| 347 | 347 |
| 348 void PowerSaveBlocker::Delegate::RemoveBlock() { | 348 void PowerSaveBlocker::Delegate::RemoveBlock() { |
| 349 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | 349 DCHECK(blocking_task_runner_->RunsTasksInCurrentSequence()); |
| 350 DCHECK(bus_); // RemoveBlock() should only be called once. | 350 DCHECK(bus_); // RemoveBlock() should only be called once. |
| 351 DCHECK(!unblock_inflight_); | 351 DCHECK(!unblock_inflight_); |
| 352 | 352 |
| 353 if (block_inflight_) { | 353 if (block_inflight_) { |
| 354 DCHECK(!enqueue_unblock_); | 354 DCHECK(!enqueue_unblock_); |
| 355 // Can't call RemoveBlock until ApplyBlock's async operation has | 355 // Can't call RemoveBlock until ApplyBlock's async operation has |
| 356 // finished. Enqueue it for execution once ApplyBlock is done. | 356 // finished. Enqueue it for execution once ApplyBlock is done. |
| 357 enqueue_unblock_ = true; | 357 enqueue_unblock_ = true; |
| 358 return; | 358 return; |
| 359 } | 359 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 | 393 |
| 394 dbus::MessageWriter message_writer(method_call.get()); | 394 dbus::MessageWriter message_writer(method_call.get()); |
| 395 message_writer.AppendUint32(inhibit_cookie_); | 395 message_writer.AppendUint32(inhibit_cookie_); |
| 396 unblock_inflight_ = true; | 396 unblock_inflight_ = true; |
| 397 object_proxy->CallMethod( | 397 object_proxy->CallMethod( |
| 398 method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, | 398 method_call.get(), dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, |
| 399 base::Bind(&PowerSaveBlocker::Delegate::RemoveBlockFinished, this)); | 399 base::Bind(&PowerSaveBlocker::Delegate::RemoveBlockFinished, this)); |
| 400 } | 400 } |
| 401 | 401 |
| 402 void PowerSaveBlocker::Delegate::RemoveBlockFinished(dbus::Response* response) { | 402 void PowerSaveBlocker::Delegate::RemoveBlockFinished(dbus::Response* response) { |
| 403 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | 403 DCHECK(blocking_task_runner_->RunsTasksInCurrentSequence()); |
| 404 DCHECK(bus_); | 404 DCHECK(bus_); |
| 405 unblock_inflight_ = false; | 405 unblock_inflight_ = false; |
| 406 | 406 |
| 407 if (!response) | 407 if (!response) |
| 408 LOG(ERROR) << "No response to Uninhibit() request!"; | 408 LOG(ERROR) << "No response to Uninhibit() request!"; |
| 409 // We don't care about checking the result. We assume it works; we can't | 409 // We don't care about checking the result. We assume it works; we can't |
| 410 // really do anything about it anyway if it fails. | 410 // really do anything about it anyway if it fails. |
| 411 inhibit_cookie_ = 0; | 411 inhibit_cookie_ = 0; |
| 412 | 412 |
| 413 bus_->ShutdownAndBlock(); | 413 bus_->ShutdownAndBlock(); |
| 414 bus_ = nullptr; | 414 bus_ = nullptr; |
| 415 } | 415 } |
| 416 | 416 |
| 417 void PowerSaveBlocker::Delegate::XSSSuspendSet(bool suspend) { | 417 void PowerSaveBlocker::Delegate::XSSSuspendSet(bool suspend) { |
| 418 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | 418 DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); |
| 419 | 419 |
| 420 if (!XSSAvailable()) | 420 if (!XSSAvailable()) |
| 421 return; | 421 return; |
| 422 | 422 |
| 423 XDisplay* display = gfx::GetXDisplay(); | 423 XDisplay* display = gfx::GetXDisplay(); |
| 424 XScreenSaverSuspend(display, suspend); | 424 XScreenSaverSuspend(display, suspend); |
| 425 } | 425 } |
| 426 | 426 |
| 427 bool PowerSaveBlocker::Delegate::DPMSEnabled() { | 427 bool PowerSaveBlocker::Delegate::DPMSEnabled() { |
| 428 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | 428 DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); |
| 429 XDisplay* display = gfx::GetXDisplay(); | 429 XDisplay* display = gfx::GetXDisplay(); |
| 430 BOOL enabled = false; | 430 BOOL enabled = false; |
| 431 int dummy; | 431 int dummy; |
| 432 if (DPMSQueryExtension(display, &dummy, &dummy) && DPMSCapable(display)) { | 432 if (DPMSQueryExtension(display, &dummy, &dummy) && DPMSCapable(display)) { |
| 433 CARD16 state; | 433 CARD16 state; |
| 434 DPMSInfo(display, &state, &enabled); | 434 DPMSInfo(display, &state, &enabled); |
| 435 } | 435 } |
| 436 return enabled; | 436 return enabled; |
| 437 } | 437 } |
| 438 | 438 |
| 439 bool PowerSaveBlocker::Delegate::XSSAvailable() { | 439 bool PowerSaveBlocker::Delegate::XSSAvailable() { |
| 440 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | 440 DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); |
| 441 // X Screen Saver isn't accessible in headless mode. | 441 // X Screen Saver isn't accessible in headless mode. |
| 442 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless)) | 442 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless)) |
| 443 return false; | 443 return false; |
| 444 XDisplay* display = gfx::GetXDisplay(); | 444 XDisplay* display = gfx::GetXDisplay(); |
| 445 int dummy; | 445 int dummy; |
| 446 int major; | 446 int major; |
| 447 int minor; | 447 int minor; |
| 448 | 448 |
| 449 if (!XScreenSaverQueryExtension(display, &dummy, &dummy)) | 449 if (!XScreenSaverQueryExtension(display, &dummy, &dummy)) |
| 450 return false; | 450 return false; |
| 451 | 451 |
| 452 if (!XScreenSaverQueryVersion(display, &major, &minor)) | 452 if (!XScreenSaverQueryVersion(display, &major, &minor)) |
| 453 return false; | 453 return false; |
| 454 | 454 |
| 455 return major > 1 || (major == 1 && minor >= 1); | 455 return major > 1 || (major == 1 && minor >= 1); |
| 456 } | 456 } |
| 457 | 457 |
| 458 DBusAPI PowerSaveBlocker::Delegate::SelectAPI() { | 458 DBusAPI PowerSaveBlocker::Delegate::SelectAPI() { |
| 459 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | 459 DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); |
| 460 // Power saving APIs are not accessible in headless mode. | 460 // Power saving APIs are not accessible in headless mode. |
| 461 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless)) | 461 if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless)) |
| 462 return NO_API; | 462 return NO_API; |
| 463 std::unique_ptr<base::Environment> env(base::Environment::Create()); | 463 std::unique_ptr<base::Environment> env(base::Environment::Create()); |
| 464 switch (base::nix::GetDesktopEnvironment(env.get())) { | 464 switch (base::nix::GetDesktopEnvironment(env.get())) { |
| 465 case base::nix::DESKTOP_ENVIRONMENT_GNOME: | 465 case base::nix::DESKTOP_ENVIRONMENT_GNOME: |
| 466 case base::nix::DESKTOP_ENVIRONMENT_UNITY: | 466 case base::nix::DESKTOP_ENVIRONMENT_UNITY: |
| 467 if (DPMSEnabled()) | 467 if (DPMSEnabled()) |
| 468 return GNOME_API; | 468 return GNOME_API; |
| 469 break; | 469 break; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 504 } | 504 } |
| 505 } | 505 } |
| 506 | 506 |
| 507 PowerSaveBlocker::~PowerSaveBlocker() { | 507 PowerSaveBlocker::~PowerSaveBlocker() { |
| 508 delegate_->CleanUp(); | 508 delegate_->CleanUp(); |
| 509 if (freedesktop_suspend_delegate_) | 509 if (freedesktop_suspend_delegate_) |
| 510 freedesktop_suspend_delegate_->CleanUp(); | 510 freedesktop_suspend_delegate_->CleanUp(); |
| 511 } | 511 } |
| 512 | 512 |
| 513 } // namespace device | 513 } // namespace device |
| OLD | NEW |