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 |