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

Side by Side Diff: content/browser/power_save_blocker_linux.cc

Issue 10218008: Linux: don't use the DBus power save blocker if DPMS is disabled. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: fix chromeos Created 8 years, 8 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "content/browser/power_save_blocker.h" 5 #include "content/browser/power_save_blocker.h"
6 6
7 #include <X11/Xlib.h>
8 #include <X11/extensions/dpms.h>
9 // Xlib #defines Status, but we can't have that for some of our headers.
10 #ifdef Status
11 #undef Status
12 #endif
13
7 #include "base/basictypes.h" 14 #include "base/basictypes.h"
8 #include "base/bind.h" 15 #include "base/bind.h"
9 #include "base/callback.h" 16 #include "base/callback.h"
10 #include "base/command_line.h" 17 #include "base/command_line.h"
11 #include "base/environment.h" 18 #include "base/environment.h"
12 #include "base/file_path.h" 19 #include "base/file_path.h"
13 #include "base/logging.h" 20 #include "base/logging.h"
14 #include "base/memory/ref_counted.h" 21 #include "base/memory/ref_counted.h"
15 #include "base/memory/scoped_ptr.h" 22 #include "base/memory/scoped_ptr.h"
16 #include "base/memory/singleton.h" 23 #include "base/memory/singleton.h"
17 #include "base/message_loop_proxy.h" 24 #include "base/message_loop_proxy.h"
25 #if defined(TOOLKIT_GTK)
26 #include "base/message_pump_gtk.h"
27 #else
28 #include "base/message_pump_x.h"
29 #endif
18 #include "base/nix/xdg_util.h" 30 #include "base/nix/xdg_util.h"
19 #include "content/public/browser/browser_thread.h" 31 #include "content/public/browser/browser_thread.h"
20 #include "dbus/bus.h" 32 #include "dbus/bus.h"
21 #include "dbus/message.h" 33 #include "dbus/message.h"
22 #include "dbus/object_path.h" 34 #include "dbus/object_path.h"
23 #include "dbus/object_proxy.h" 35 #include "dbus/object_proxy.h"
24 36
25 using content::BrowserThread; 37 using content::BrowserThread;
26 38
27 namespace { 39 namespace {
28 40
29 // This class is used to inhibit Power Management on Linux systems 41 // This class is used to inhibit Power Management on Linux systems using D-Bus
30 // using D-Bus interfaces. Mainly, there are two interfaces that 42 // interfaces. Mainly, there are two interfaces that make this possible.
31 // make this possible. 43 // org.freedesktop.PowerManagement[.Inhibit] is considered to be the
32 // org.freedesktop.PowerManagement[.Inhibit] is considered to be 44 // desktop-agnostic solution. However, it is only used by KDE4 and XFCE.
33 // the desktop-agnostic solution. However, it is only used by 45 //
34 // KDE4 and XFCE. 46 // org.gnome.SessionManager is the Power Management interface available on GNOME
35 // org.gnome.SessionManager is the Power Management interface 47 // desktops. Given that there is no generic solution to this problem, this class
36 // available on Gnome desktops. 48 // delegates the task of calling specific D-Bus APIs, to a
37 // Given that there is no generic solution to this problem, 49 // DBusPowerSaveBlock::Delegate object.
38 // this class delegates the task of calling specific D-Bus APIs, 50 //
39 // to a DBusPowerSaveBlock::Delegate object. 51 // This class is a Singleton and the delegate will be instantiated internally,
40 // This class is a Singleton and the delegate will be instantiated 52 // when the singleton instance is created, based on the desktop environment in
41 // internally, when the singleton instance is created, based on 53 // which the application is running. When the class is instantiated, if it runs
42 // the desktop environment in which the application is running. 54 // under a supported desktop environment it creates the Bus object and the
43 // When the class is instantiated, if it runs under a supported 55 // delegate. Otherwise, no object is created and the ApplyBlock method will not
44 // desktop environment it creates the Bus object and the 56 // do anything.
45 // delegate. Otherwise, no object is created and the ApplyBlock
46 // method will not do anything.
47 class DBusPowerSaveBlocker { 57 class DBusPowerSaveBlocker {
48 public: 58 public:
49 // String passed to D-Bus APIs as the reason for which 59 // String passed to D-Bus APIs as the reason for which
50 // the power management features are temporarily disabled. 60 // the power management features are temporarily disabled.
51 static const char kPowerSaveReason[]; 61 static const char kPowerSaveReason[];
52 62
53 // This delegate interface represents a concrete 63 // This delegate interface represents a concrete implementation for a specific
54 // implementation for a specific D-Bus interface. 64 // D-Bus interface. It is responsible for obtaining specific object proxies,
55 // It is responsible for obtaining specific object proxies,
56 // making D-Bus method calls and handling D-Bus responses. 65 // making D-Bus method calls and handling D-Bus responses.
57 // When a new DBusPowerBlocker is created, only a specific 66 //
58 // implementation of the delegate is instantiated. See the 67 // When a new DBusPowerBlocker is created, only a specific implementation of
59 // DBusPowerSaveBlocker constructor for more details. 68 // the delegate is instantiated. See the DBusPowerSaveBlocker constructor for
60 // This is ref_counted to make sure that the callbacks 69 // more details. This is ref_counted to make sure that the callbacks stay
61 // stay alive even after the DBusPowerSaveBlocker object 70 // alive even after the DBusPowerSaveBlocker object is deleted.
62 // is deleted.
63 class Delegate : public base::RefCountedThreadSafe<Delegate> { 71 class Delegate : public base::RefCountedThreadSafe<Delegate> {
64 public: 72 public:
65 Delegate() {} 73 Delegate() {}
66 virtual ~Delegate() {} 74 virtual ~Delegate() {}
67 virtual void ApplyBlock(PowerSaveBlocker::PowerSaveBlockerType type) = 0; 75 virtual void ApplyBlock(PowerSaveBlocker::PowerSaveBlockerType type) = 0;
68 private: 76 private:
69 DISALLOW_COPY_AND_ASSIGN(Delegate); 77 DISALLOW_COPY_AND_ASSIGN(Delegate);
70 }; 78 };
71 79
72 // Returns a pointer to the sole instance of this class 80 // Returns a pointer to the sole instance of this class
73 static DBusPowerSaveBlocker* GetInstance(); 81 static DBusPowerSaveBlocker* GetInstance();
74 82
75 // Forwards a power save block request to the concrete implementation 83 // Forwards a power save block request to the concrete implementation of the
76 // of the Delegate interface. 84 // Delegate interface. If |delegate_| is NULL, the application runs under an
77 // If |delegate_| is NULL, the application runs under an unsupported 85 // unsupported desktop environment. In this case, the method does nothing.
78 // desktop environment. In this case, the method doesn't do anything.
79 void ApplyBlock(PowerSaveBlocker::PowerSaveBlockerType type) { 86 void ApplyBlock(PowerSaveBlocker::PowerSaveBlockerType type) {
80 if (delegate_) 87 if (delegate_)
81 delegate_->ApplyBlock(type); 88 delegate_->ApplyBlock(type);
82 } 89 }
83 90
84 // Getter for the Bus object. Used by the Delegates to obtain object proxies. 91 // Getter for the Bus object. Used by the Delegates to obtain object proxies.
85 scoped_refptr<dbus::Bus> bus() const { return bus_; } 92 scoped_refptr<dbus::Bus> bus() const { return bus_; }
86 93
87 private: 94 private:
88 DBusPowerSaveBlocker(); 95 DBusPowerSaveBlocker();
89 virtual ~DBusPowerSaveBlocker(); 96 virtual ~DBusPowerSaveBlocker();
90 97
98 // If DPMS is not enabled, then we don't want to try to disable power saving,
99 // since on some desktop environments that may enable DPMS with very poor
100 // default settings (e.g. turning off the display after only 1 second).
101 static bool DPMSEnabled();
102
91 // The D-Bus connection. 103 // The D-Bus connection.
92 scoped_refptr<dbus::Bus> bus_; 104 scoped_refptr<dbus::Bus> bus_;
93 105
94 // Concrete implementation of the Delegate interface. 106 // Concrete implementation of the Delegate interface.
95 scoped_refptr<Delegate> delegate_; 107 scoped_refptr<Delegate> delegate_;
96 108
97 friend struct DefaultSingletonTraits<DBusPowerSaveBlocker>; 109 friend struct DefaultSingletonTraits<DBusPowerSaveBlocker>;
98 110
99 DISALLOW_COPY_AND_ASSIGN(DBusPowerSaveBlocker); 111 DISALLOW_COPY_AND_ASSIGN(DBusPowerSaveBlocker);
100 }; 112 };
101 113
102 // Delegate implementation for KDE4. 114 // Delegate implementation for KDE4. It uses the
103 // It uses the org.freedesktop.PowerManagement interface. 115 // org.freedesktop.PowerManagement interface. It works on XFCE4, too.
104 // Works on XFCE4, too.
105 class KDEPowerSaveBlocker : public DBusPowerSaveBlocker::Delegate { 116 class KDEPowerSaveBlocker : public DBusPowerSaveBlocker::Delegate {
106 public: 117 public:
107 KDEPowerSaveBlocker() 118 KDEPowerSaveBlocker()
108 : inhibit_cookie_(0), 119 : inhibit_cookie_(0),
109 pending_inhibit_call_(false), 120 pending_inhibit_call_(false),
110 postponed_uninhibit_call_(false) {} 121 postponed_uninhibit_call_(false) {
122 }
111 ~KDEPowerSaveBlocker() {} 123 ~KDEPowerSaveBlocker() {}
112 124
113 virtual void ApplyBlock( 125 virtual void ApplyBlock(
114 PowerSaveBlocker::PowerSaveBlockerType type) OVERRIDE { 126 PowerSaveBlocker::PowerSaveBlockerType type) OVERRIDE {
115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 127 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
116 DCHECK(pending_inhibit_call_ || !postponed_uninhibit_call_); 128 DCHECK(pending_inhibit_call_ || !postponed_uninhibit_call_);
117 129
118 // If we have a pending inhibit call, we add a postponed uninhibit 130 // If we have a pending inhibit call, we add a postponed uninhibit
119 // request, such that it will be canceled as soon as the response arrives. 131 // request, such that it will be canceled as soon as the response arrives.
120 // If we have an active inhibit request and receive a new one, 132 // If we have an active inhibit request and receive a new one,
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 : inhibit_cookie_(0), 258 : inhibit_cookie_(0),
247 pending_inhibit_calls_(0), 259 pending_inhibit_calls_(0),
248 postponed_uninhibit_calls_(0) {} 260 postponed_uninhibit_calls_(0) {}
249 ~GnomePowerSaveBlocker() {} 261 ~GnomePowerSaveBlocker() {}
250 262
251 virtual void ApplyBlock( 263 virtual void ApplyBlock(
252 PowerSaveBlocker::PowerSaveBlockerType type) OVERRIDE { 264 PowerSaveBlocker::PowerSaveBlockerType type) OVERRIDE {
253 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
254 DCHECK(postponed_uninhibit_calls_ <= pending_inhibit_calls_); 266 DCHECK(postponed_uninhibit_calls_ <= pending_inhibit_calls_);
255 267
256 // If we have a pending inhibit call, we add a postponed uninhibit 268 // If we have a pending inhibit call, we add a postponed uninhibit request,
257 // request, such that it will be canceled as soon as the response arrives. 269 // such that it will be canceled as soon as the response arrives. We want to
258 // We want to cancel the current inhibit request whether |type| is 270 // cancel the current inhibit request whether |type| is
259 // kPowerSaveBlockPreventNone or not. If |type| represents an inhibit 271 // kPowerSaveBlockPreventNone or not. If |type| represents an inhibit
260 // request, we are dealing with the same case as below, just that the 272 // request, we are dealing with the same case as below, just that the reply
261 // reply to the previous inhibit request did not arrive yet, so we have 273 // to the previous inhibit request did not arrive yet, so we have to wait
262 // to wait for the cookie in order to cancel it. 274 // for the cookie in order to cancel it. Meanwhile, we can still make the
263 // Meanwhile, we can still make the new request. 275 // new request.
264 // We also have to check that 276 //
265 // postponed_uninhibit_calls_ < pending_inhibit_calls_. 277 // We also have to check that postponed_uninhibit_calls_ <
266 // If this is not the case, then all the pending requests were already 278 // pending_inhibit_calls_. If this is not the case, then all the pending
267 // canceled and we should not increment the number of postponed uninhibit 279 // requests were already canceled and we should not increment the number of
268 // requests; otherwise we will cancel unwanted future inhibits, 280 // postponed uninhibit requests; otherwise we will cancel unwanted future
269 // that will be made after this call. 281 // inhibits, that will be made after this call.
270 // NOTE: The implementation is based on the fact that we receive 282 //
271 // the D-Bus replies in the same order in which the requests are made. 283 // NOTE: The implementation is based on the fact that we receive the D-Bus
284 // replies in the same order in which the requests are made.
272 if (pending_inhibit_calls_ > 0 && 285 if (pending_inhibit_calls_ > 0 &&
273 postponed_uninhibit_calls_ < pending_inhibit_calls_) { 286 postponed_uninhibit_calls_ < pending_inhibit_calls_) {
274 ++postponed_uninhibit_calls_; 287 ++postponed_uninhibit_calls_;
275 // If the call was an Uninhibit, then we are done for the moment. 288 // If the call was an Uninhibit, then we are done for the moment.
276 if (type == PowerSaveBlocker::kPowerSaveBlockPreventNone) 289 if (type == PowerSaveBlocker::kPowerSaveBlockPreventNone)
277 return; 290 return;
278 } 291 }
279 292
280 // If we have an active inhibit request and no pending inhibit calls, 293 // If we have an active inhibit request and no pending inhibit calls,
281 // we make an uninhibit request to cancel it now. 294 // we make an uninhibit request to cancel it now.
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 // org.gnome.SessionManager.Uninhibit(). 351 // org.gnome.SessionManager.Uninhibit().
339 // It takes only one argument, the cookie that identifies 352 // It takes only one argument, the cookie that identifies
340 // the request we want to cancel. 353 // the request we want to cancel.
341 method_call.SetMember("Uninhibit"); 354 method_call.SetMember("Uninhibit");
342 message_writer.AppendUint32(inhibit_cookie_); 355 message_writer.AppendUint32(inhibit_cookie_);
343 bus_callback = base::Bind(&GnomePowerSaveBlocker::OnUnInhibitResponse, 356 bus_callback = base::Bind(&GnomePowerSaveBlocker::OnUnInhibitResponse,
344 this); 357 this);
345 ++pending_inhibit_calls_; 358 ++pending_inhibit_calls_;
346 break; 359 break;
347 case PowerSaveBlocker::kPowerSaveBlockPreventStateCount: 360 case PowerSaveBlocker::kPowerSaveBlockPreventStateCount:
348 // This is an invalid argument; 361 // This is an invalid argument.
349 NOTREACHED(); 362 NOTREACHED();
350 break; 363 break;
351 } 364 }
352 365
353 object_proxy->CallMethod(&method_call, 366 object_proxy->CallMethod(&method_call,
354 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 367 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
355 bus_callback); 368 bus_callback);
356 } 369 }
357 370
358 private: 371 private:
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 421
409 // Initialize the DBusPowerSaveBlocker instance: 422 // Initialize the DBusPowerSaveBlocker instance:
410 // 1. Instantiate a concrete delegate based on the current desktop environment, 423 // 1. Instantiate a concrete delegate based on the current desktop environment,
411 // 2. Instantiate the D-Bus object 424 // 2. Instantiate the D-Bus object
412 DBusPowerSaveBlocker::DBusPowerSaveBlocker() { 425 DBusPowerSaveBlocker::DBusPowerSaveBlocker() {
413 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 426 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
414 427
415 scoped_ptr<base::Environment> env(base::Environment::Create()); 428 scoped_ptr<base::Environment> env(base::Environment::Create());
416 switch (base::nix::GetDesktopEnvironment(env.get())) { 429 switch (base::nix::GetDesktopEnvironment(env.get())) {
417 case base::nix::DESKTOP_ENVIRONMENT_GNOME: 430 case base::nix::DESKTOP_ENVIRONMENT_GNOME:
418 delegate_ = new GnomePowerSaveBlocker(); 431 if (DPMSEnabled())
432 delegate_ = new GnomePowerSaveBlocker();
419 break; 433 break;
420 case base::nix::DESKTOP_ENVIRONMENT_XFCE: 434 case base::nix::DESKTOP_ENVIRONMENT_XFCE:
421 case base::nix::DESKTOP_ENVIRONMENT_KDE4: 435 case base::nix::DESKTOP_ENVIRONMENT_KDE4:
422 delegate_ = new KDEPowerSaveBlocker(); 436 if (DPMSEnabled())
437 delegate_ = new KDEPowerSaveBlocker();
423 break; 438 break;
424 case base::nix::DESKTOP_ENVIRONMENT_KDE3: 439 case base::nix::DESKTOP_ENVIRONMENT_KDE3:
425 case base::nix::DESKTOP_ENVIRONMENT_OTHER: 440 case base::nix::DESKTOP_ENVIRONMENT_OTHER:
426 // Not supported, so we exit. 441 // Not supported, so we exit.
427 // We don't create D-Bus objects. 442 // We don't create D-Bus objects.
428 break; 443 break;
429 } 444 }
430 445
431 if (delegate_) { 446 if (delegate_) {
432 dbus::Bus::Options options; 447 dbus::Bus::Options options;
(...skipping 16 matching lines...) Expand all
449 // we are at the very end of the shutting down phase. 464 // we are at the very end of the shutting down phase.
450 // Connection to D-Bus is just a Unix domain socket, which is not 465 // Connection to D-Bus is just a Unix domain socket, which is not
451 // a persistent resource, hence the operating system will take care 466 // a persistent resource, hence the operating system will take care
452 // of closing it when the process terminates. 467 // of closing it when the process terminates.
453 if (BrowserThread::IsMessageLoopValid(BrowserThread::FILE)) { 468 if (BrowserThread::IsMessageLoopValid(BrowserThread::FILE)) {
454 bus_->ShutdownOnDBusThreadAndBlock(); 469 bus_->ShutdownOnDBusThreadAndBlock();
455 } 470 }
456 } 471 }
457 472
458 // static 473 // static
474 bool DBusPowerSaveBlocker::DPMSEnabled() {
475 #if defined(TOOLKIT_GTK)
476 Display* display = base::MessagePumpGtk::GetDefaultXDisplay();
477 #else
478 Display* display = base::MessagePumpX::GetDefaultXDisplay();
479 #endif
480 BOOL enabled = false;
481 int dummy;
482 if (DPMSQueryExtension(display, &dummy, &dummy) && DPMSCapable(display)) {
483 CARD16 state;
484 DPMSInfo(display, &state, &enabled);
485 }
486 return enabled;
487 }
488
489 // static
459 DBusPowerSaveBlocker* DBusPowerSaveBlocker::GetInstance() { 490 DBusPowerSaveBlocker* DBusPowerSaveBlocker::GetInstance() {
460 return Singleton<DBusPowerSaveBlocker>::get(); 491 return Singleton<DBusPowerSaveBlocker>::get();
461 } 492 }
462 493
463 } // namespace 494 } // namespace
464 495
465 // Called only from UI thread. 496 // Called only from UI thread.
466 // static 497 // static
467 void PowerSaveBlocker::ApplyBlock(PowerSaveBlockerType type) { 498 void PowerSaveBlocker::ApplyBlock(PowerSaveBlockerType type) {
468 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 499 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
469 DBusPowerSaveBlocker::GetInstance()->ApplyBlock(type); 500 DBusPowerSaveBlocker::GetInstance()->ApplyBlock(type);
470 } 501 }
OLDNEW
« 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