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

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

Issue 11784016: chromeos: Block system suspend while uploading files to Drive (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: PowerSaveBlocker is a pure interface Created 7 years, 11 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
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/public/browser/power_save_blocker.h"
6 6
7 #include <X11/Xlib.h> 7 #include <X11/Xlib.h>
8 #include <X11/extensions/dpms.h> 8 #include <X11/extensions/dpms.h>
9 // Xlib #defines Status, but we can't have that for some of our headers. 9 // Xlib #defines Status, but we can't have that for some of our headers.
10 #ifdef Status 10 #ifdef Status
11 #undef Status 11 #undef Status
12 #endif 12 #endif
13 13
14 #include "base/basictypes.h" 14 #include "base/basictypes.h"
15 #include "base/bind.h" 15 #include "base/bind.h"
(...skipping 12 matching lines...) Expand all
28 #include "base/message_pump_aurax11.h" 28 #include "base/message_pump_aurax11.h"
29 #endif 29 #endif
30 #include "base/nix/xdg_util.h" 30 #include "base/nix/xdg_util.h"
31 #include "base/synchronization/lock.h" 31 #include "base/synchronization/lock.h"
32 #include "content/public/browser/browser_thread.h" 32 #include "content/public/browser/browser_thread.h"
33 #include "dbus/bus.h" 33 #include "dbus/bus.h"
34 #include "dbus/message.h" 34 #include "dbus/message.h"
35 #include "dbus/object_path.h" 35 #include "dbus/object_path.h"
36 #include "dbus/object_proxy.h" 36 #include "dbus/object_proxy.h"
37 37
38 namespace content {
39
38 namespace { 40 namespace {
39 41
40 enum DBusAPI { 42 enum DBusAPI {
41 NO_API, // Disable. No supported API available. 43 NO_API, // Disable. No supported API available.
42 GNOME_API, // Use the GNOME API. (Supports more features.) 44 GNOME_API, // Use the GNOME API. (Supports more features.)
43 FREEDESKTOP_API, // Use the FreeDesktop API, for KDE4 and XFCE. 45 FREEDESKTOP_API, // Use the FreeDesktop API, for KDE4 and XFCE.
44 }; 46 };
45 47
46 // Inhibit flags defined in the org.gnome.SessionManager interface. 48 // Inhibit flags defined in the org.gnome.SessionManager interface.
47 // Can be OR'd together and passed as argument to the Inhibit() method 49 // Can be OR'd together and passed as argument to the Inhibit() method
48 // to specify which power management features we want to suspend. 50 // to specify which power management features we want to suspend.
49 enum GnomeAPIInhibitFlags { 51 enum GnomeAPIInhibitFlags {
50 INHIBIT_LOGOUT = 1, 52 INHIBIT_LOGOUT = 1,
51 INHIBIT_SWITCH_USER = 2, 53 INHIBIT_SWITCH_USER = 2,
52 INHIBIT_SUSPEND_SESSION = 4, 54 INHIBIT_SUSPEND_SESSION = 4,
53 INHIBIT_MARK_SESSION_IDLE = 8 55 INHIBIT_MARK_SESSION_IDLE = 8
54 }; 56 };
55 57
56 const char kGnomeAPIServiceName[] = "org.gnome.SessionManager"; 58 const char kGnomeAPIServiceName[] = "org.gnome.SessionManager";
57 const char kGnomeAPIInterfaceName[] = "org.gnome.SessionManager"; 59 const char kGnomeAPIInterfaceName[] = "org.gnome.SessionManager";
58 const char kGnomeAPIObjectPath[] = "/org/gnome/SessionManager"; 60 const char kGnomeAPIObjectPath[] = "/org/gnome/SessionManager";
59 61
60 const char kFreeDesktopAPIServiceName[] = "org.freedesktop.PowerManagement"; 62 const char kFreeDesktopAPIServiceName[] = "org.freedesktop.PowerManagement";
61 const char kFreeDesktopAPIInterfaceName[] = 63 const char kFreeDesktopAPIInterfaceName[] =
62 "org.freedesktop.PowerManagement.Inhibit"; 64 "org.freedesktop.PowerManagement.Inhibit";
63 const char kFreeDesktopAPIObjectPath[] = 65 const char kFreeDesktopAPIObjectPath[] =
64 "/org/freedesktop/PowerManagement/Inhibit"; 66 "/org/freedesktop/PowerManagement/Inhibit";
65 67
66 } // anonymous namespace 68 class PowerSaveBlockerLinux : public PowerSaveBlocker {
69 public:
70 PowerSaveBlockerLinux(PowerSaveBlockerType type, const std::string& reason);
71 virtual ~PowerSaveBlockerLinux();
67 72
68 namespace content { 73 private:
74 class Delegate;
69 75
70 class PowerSaveBlocker::Delegate 76 // A second object with different lifetime than the RAII container.
71 : public base::RefCountedThreadSafe<PowerSaveBlocker::Delegate> { 77 scoped_refptr<Delegate> delegate_;
78
79 DISALLOW_COPY_AND_ASSIGN(PowerSaveBlockerLinux);
80 };
81
82 class PowerSaveBlockerLinux::Delegate
83 : public base::RefCountedThreadSafe<PowerSaveBlockerLinux::Delegate> {
72 public: 84 public:
73 // Picks an appropriate D-Bus API to use based on the desktop environment. 85 // Picks an appropriate D-Bus API to use based on the desktop environment.
74 Delegate(PowerSaveBlockerType type, const std::string& reason); 86 Delegate(PowerSaveBlockerType type, const std::string& reason);
75 87
76 // Post a task to initialize the delegate on the UI thread, which will itself 88 // Post a task to initialize the delegate on the UI thread, which will itself
77 // then post a task to apply the power save block on the FILE thread. 89 // then post a task to apply the power save block on the FILE thread.
78 void Init(); 90 void Init();
79 91
80 // Post a task to remove the power save block on the FILE thread, unless it 92 // Post a task to remove the power save block on the FILE thread, unless it
81 // hasn't yet been applied, in which case we just prevent it from applying. 93 // hasn't yet been applied, in which case we just prevent it from applying.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 133
122 scoped_refptr<dbus::Bus> bus_; 134 scoped_refptr<dbus::Bus> bus_;
123 135
124 // The cookie that identifies our inhibit request, 136 // The cookie that identifies our inhibit request,
125 // or 0 if there is no active inhibit request. 137 // or 0 if there is no active inhibit request.
126 uint32 inhibit_cookie_; 138 uint32 inhibit_cookie_;
127 139
128 DISALLOW_COPY_AND_ASSIGN(Delegate); 140 DISALLOW_COPY_AND_ASSIGN(Delegate);
129 }; 141 };
130 142
131 PowerSaveBlocker::Delegate::Delegate(PowerSaveBlockerType type, 143 PowerSaveBlockerLinux::Delegate::Delegate(PowerSaveBlockerType type,
132 const std::string& reason) 144 const std::string& reason)
133 : type_(type), 145 : type_(type),
134 reason_(reason), 146 reason_(reason),
135 api_(NO_API), 147 api_(NO_API),
136 enqueue_apply_(false), 148 enqueue_apply_(false),
137 inhibit_cookie_(0) { 149 inhibit_cookie_(0) {
138 // We're on the client's thread here, so we don't allocate the dbus::Bus 150 // We're on the client's thread here, so we don't allocate the dbus::Bus
139 // object yet. We'll do it later in ApplyBlock(), on the FILE thread. 151 // object yet. We'll do it later in ApplyBlock(), on the FILE thread.
140 } 152 }
141 153
142 void PowerSaveBlocker::Delegate::Init() { 154 void PowerSaveBlockerLinux::Delegate::Init() {
143 base::AutoLock lock(lock_); 155 base::AutoLock lock(lock_);
144 DCHECK(!enqueue_apply_); 156 DCHECK(!enqueue_apply_);
145 enqueue_apply_ = true; 157 enqueue_apply_ = true;
146 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 158 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
147 base::Bind(&Delegate::InitOnUIThread, this)); 159 base::Bind(&Delegate::InitOnUIThread, this));
148 } 160 }
149 161
150 void PowerSaveBlocker::Delegate::CleanUp() { 162 void PowerSaveBlockerLinux::Delegate::CleanUp() {
151 base::AutoLock lock(lock_); 163 base::AutoLock lock(lock_);
152 if (enqueue_apply_) { 164 if (enqueue_apply_) {
153 // If a call to ApplyBlock() has not yet been enqueued because we are still 165 // If a call to ApplyBlock() has not yet been enqueued because we are still
154 // initializing on the UI thread, then just cancel it. We don't need to 166 // initializing on the UI thread, then just cancel it. We don't need to
155 // remove the block because we haven't even applied it yet. 167 // remove the block because we haven't even applied it yet.
156 enqueue_apply_ = false; 168 enqueue_apply_ = false;
157 } else if (api_ != NO_API) { 169 } else if (api_ != NO_API) {
158 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 170 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
159 base::Bind(&Delegate::RemoveBlock, this, api_)); 171 base::Bind(&Delegate::RemoveBlock, this, api_));
160 } 172 }
161 } 173 }
162 174
163 void PowerSaveBlocker::Delegate::InitOnUIThread() { 175 void PowerSaveBlockerLinux::Delegate::InitOnUIThread() {
164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
165 base::AutoLock lock(lock_); 177 base::AutoLock lock(lock_);
166 api_ = SelectAPI(); 178 api_ = SelectAPI();
167 if (enqueue_apply_ && api_ != NO_API) { 179 if (enqueue_apply_ && api_ != NO_API) {
168 // The thread we use here becomes the origin and D-Bus thread for the D-Bus 180 // The thread we use here becomes the origin and D-Bus thread for the D-Bus
169 // library, so we need to use the same thread above for RemoveBlock(). It 181 // library, so we need to use the same thread above for RemoveBlock(). It
170 // must be a thread that allows I/O operations, so we use the FILE thread. 182 // must be a thread that allows I/O operations, so we use the FILE thread.
171 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 183 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
172 base::Bind(&Delegate::ApplyBlock, this, api_)); 184 base::Bind(&Delegate::ApplyBlock, this, api_));
173 } 185 }
174 enqueue_apply_ = false; 186 enqueue_apply_ = false;
175 } 187 }
176 188
177 void PowerSaveBlocker::Delegate::ApplyBlock(DBusAPI api) { 189 void PowerSaveBlockerLinux::Delegate::ApplyBlock(DBusAPI api) {
178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
179 DCHECK(!bus_.get()); // ApplyBlock() should only be called once. 191 DCHECK(!bus_.get()); // ApplyBlock() should only be called once.
180 192
181 dbus::Bus::Options options; 193 dbus::Bus::Options options;
182 options.bus_type = dbus::Bus::SESSION; 194 options.bus_type = dbus::Bus::SESSION;
183 options.connection_type = dbus::Bus::PRIVATE; 195 options.connection_type = dbus::Bus::PRIVATE;
184 bus_ = new dbus::Bus(options); 196 bus_ = new dbus::Bus(options);
185 197
186 scoped_refptr<dbus::ObjectProxy> object_proxy; 198 scoped_refptr<dbus::ObjectProxy> object_proxy;
187 scoped_ptr<dbus::MethodCall> method_call; 199 scoped_ptr<dbus::MethodCall> method_call;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 // this request. It should be used as an argument to Uninhibit() 259 // this request. It should be used as an argument to Uninhibit()
248 // in order to remove the request. 260 // in order to remove the request.
249 dbus::MessageReader message_reader(response.get()); 261 dbus::MessageReader message_reader(response.get());
250 if (!message_reader.PopUint32(&inhibit_cookie_)) 262 if (!message_reader.PopUint32(&inhibit_cookie_))
251 LOG(ERROR) << "Invalid Inhibit() response: " << response->ToString(); 263 LOG(ERROR) << "Invalid Inhibit() response: " << response->ToString();
252 } else { 264 } else {
253 LOG(ERROR) << "No response to Inhibit() request!"; 265 LOG(ERROR) << "No response to Inhibit() request!";
254 } 266 }
255 } 267 }
256 268
257 void PowerSaveBlocker::Delegate::RemoveBlock(DBusAPI api) { 269 void PowerSaveBlockerLinux::Delegate::RemoveBlock(DBusAPI api) {
258 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 270 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
259 DCHECK(bus_.get()); // RemoveBlock() should only be called once. 271 DCHECK(bus_.get()); // RemoveBlock() should only be called once.
260 272
261 scoped_refptr<dbus::ObjectProxy> object_proxy; 273 scoped_refptr<dbus::ObjectProxy> object_proxy;
262 scoped_ptr<dbus::MethodCall> method_call; 274 scoped_ptr<dbus::MethodCall> method_call;
263 275
264 switch (api) { 276 switch (api) {
265 case NO_API: 277 case NO_API:
266 NOTREACHED(); // We should never call this method with this value. 278 NOTREACHED(); // We should never call this method with this value.
267 return; 279 return;
(...skipping 21 matching lines...) Expand all
289 LOG(ERROR) << "No response to Uninhibit() request!"; 301 LOG(ERROR) << "No response to Uninhibit() request!";
290 // We don't care about checking the result. We assume it works; we can't 302 // We don't care about checking the result. We assume it works; we can't
291 // really do anything about it anyway if it fails. 303 // really do anything about it anyway if it fails.
292 inhibit_cookie_ = 0; 304 inhibit_cookie_ = 0;
293 305
294 bus_->ShutdownAndBlock(); 306 bus_->ShutdownAndBlock();
295 bus_ = NULL; 307 bus_ = NULL;
296 } 308 }
297 309
298 // static 310 // static
299 bool PowerSaveBlocker::Delegate::DPMSEnabled() { 311 bool PowerSaveBlockerLinux::Delegate::DPMSEnabled() {
300 Display* display = base::MessagePumpForUI::GetDefaultXDisplay(); 312 Display* display = base::MessagePumpForUI::GetDefaultXDisplay();
301 BOOL enabled = false; 313 BOOL enabled = false;
302 int dummy; 314 int dummy;
303 if (DPMSQueryExtension(display, &dummy, &dummy) && DPMSCapable(display)) { 315 if (DPMSQueryExtension(display, &dummy, &dummy) && DPMSCapable(display)) {
304 CARD16 state; 316 CARD16 state;
305 DPMSInfo(display, &state, &enabled); 317 DPMSInfo(display, &state, &enabled);
306 } 318 }
307 return enabled; 319 return enabled;
308 } 320 }
309 321
310 // static 322 // static
311 DBusAPI PowerSaveBlocker::Delegate::SelectAPI() { 323 DBusAPI PowerSaveBlockerLinux::Delegate::SelectAPI() {
312 scoped_ptr<base::Environment> env(base::Environment::Create()); 324 scoped_ptr<base::Environment> env(base::Environment::Create());
313 switch (base::nix::GetDesktopEnvironment(env.get())) { 325 switch (base::nix::GetDesktopEnvironment(env.get())) {
314 case base::nix::DESKTOP_ENVIRONMENT_GNOME: 326 case base::nix::DESKTOP_ENVIRONMENT_GNOME:
315 case base::nix::DESKTOP_ENVIRONMENT_UNITY: 327 case base::nix::DESKTOP_ENVIRONMENT_UNITY:
316 if (DPMSEnabled()) 328 if (DPMSEnabled())
317 return GNOME_API; 329 return GNOME_API;
318 break; 330 break;
319 case base::nix::DESKTOP_ENVIRONMENT_XFCE: 331 case base::nix::DESKTOP_ENVIRONMENT_XFCE:
320 case base::nix::DESKTOP_ENVIRONMENT_KDE4: 332 case base::nix::DESKTOP_ENVIRONMENT_KDE4:
321 if (DPMSEnabled()) 333 if (DPMSEnabled())
322 return FREEDESKTOP_API; 334 return FREEDESKTOP_API;
323 break; 335 break;
324 case base::nix::DESKTOP_ENVIRONMENT_KDE3: 336 case base::nix::DESKTOP_ENVIRONMENT_KDE3:
325 case base::nix::DESKTOP_ENVIRONMENT_OTHER: 337 case base::nix::DESKTOP_ENVIRONMENT_OTHER:
326 // Not supported. 338 // Not supported.
327 break; 339 break;
328 } 340 }
329 return NO_API; 341 return NO_API;
330 } 342 }
331 343
332 PowerSaveBlocker::PowerSaveBlocker( 344 PowerSaveBlockerLinux::PowerSaveBlockerLinux(
333 PowerSaveBlockerType type, const std::string& reason) 345 PowerSaveBlockerType type, const std::string& reason)
334 : delegate_(new Delegate(type, reason)) { 346 : delegate_(new Delegate(type, reason)) {
335 delegate_->Init(); 347 delegate_->Init();
336 } 348 }
337 349
338 PowerSaveBlocker::~PowerSaveBlocker() { 350 PowerSaveBlockerLinux::~PowerSaveBlockerLinux() {
339 delegate_->CleanUp(); 351 delegate_->CleanUp();
340 } 352 }
341 353
354 } // namespace
355
356 // static
357 scoped_ptr<PowerSaveBlocker> PowerSaveBlocker::Create(
358 PowerSaveBlockerType type,
359 const std::string& reason) {
360 return scoped_ptr<PowerSaveBlocker>(new PowerSaveBlockerLinux(type, reason));
361 }
362
342 } // namespace content 363 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698