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 "content/browser/power_save_blocker.h" | 5 #include "content/browser/power_save_blocker_impl.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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 const char kGnomeAPIServiceName[] = "org.gnome.SessionManager"; | 56 const char kGnomeAPIServiceName[] = "org.gnome.SessionManager"; |
57 const char kGnomeAPIInterfaceName[] = "org.gnome.SessionManager"; | 57 const char kGnomeAPIInterfaceName[] = "org.gnome.SessionManager"; |
58 const char kGnomeAPIObjectPath[] = "/org/gnome/SessionManager"; | 58 const char kGnomeAPIObjectPath[] = "/org/gnome/SessionManager"; |
59 | 59 |
60 const char kFreeDesktopAPIServiceName[] = "org.freedesktop.PowerManagement"; | 60 const char kFreeDesktopAPIServiceName[] = "org.freedesktop.PowerManagement"; |
61 const char kFreeDesktopAPIInterfaceName[] = | 61 const char kFreeDesktopAPIInterfaceName[] = |
62 "org.freedesktop.PowerManagement.Inhibit"; | 62 "org.freedesktop.PowerManagement.Inhibit"; |
63 const char kFreeDesktopAPIObjectPath[] = | 63 const char kFreeDesktopAPIObjectPath[] = |
64 "/org/freedesktop/PowerManagement/Inhibit"; | 64 "/org/freedesktop/PowerManagement/Inhibit"; |
65 | 65 |
66 } // anonymous namespace | 66 } // namespace |
67 | 67 |
68 namespace content { | 68 namespace content { |
69 | 69 |
70 class PowerSaveBlocker::Delegate | 70 class PowerSaveBlockerImpl::Delegate |
71 : public base::RefCountedThreadSafe<PowerSaveBlocker::Delegate> { | 71 : public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> { |
72 public: | 72 public: |
73 // Picks an appropriate D-Bus API to use based on the desktop environment. | 73 // Picks an appropriate D-Bus API to use based on the desktop environment. |
74 Delegate(PowerSaveBlockerType type, const std::string& reason); | 74 Delegate(PowerSaveBlockerType type, const std::string& reason); |
75 | 75 |
76 // Post a task to initialize the delegate on the UI thread, which will itself | 76 // 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. | 77 // then post a task to apply the power save block on the FILE thread. |
78 void Init(); | 78 void Init(); |
79 | 79 |
80 // Post a task to remove the power save block on the FILE thread, unless it | 80 // 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. | 81 // 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 Loading... |
121 | 121 |
122 scoped_refptr<dbus::Bus> bus_; | 122 scoped_refptr<dbus::Bus> bus_; |
123 | 123 |
124 // The cookie that identifies our inhibit request, | 124 // The cookie that identifies our inhibit request, |
125 // or 0 if there is no active inhibit request. | 125 // or 0 if there is no active inhibit request. |
126 uint32 inhibit_cookie_; | 126 uint32 inhibit_cookie_; |
127 | 127 |
128 DISALLOW_COPY_AND_ASSIGN(Delegate); | 128 DISALLOW_COPY_AND_ASSIGN(Delegate); |
129 }; | 129 }; |
130 | 130 |
131 PowerSaveBlocker::Delegate::Delegate(PowerSaveBlockerType type, | 131 PowerSaveBlockerImpl::Delegate::Delegate(PowerSaveBlockerType type, |
132 const std::string& reason) | 132 const std::string& reason) |
133 : type_(type), | 133 : type_(type), |
134 reason_(reason), | 134 reason_(reason), |
135 api_(NO_API), | 135 api_(NO_API), |
136 enqueue_apply_(false), | 136 enqueue_apply_(false), |
137 inhibit_cookie_(0) { | 137 inhibit_cookie_(0) { |
138 // We're on the client's thread here, so we don't allocate the dbus::Bus | 138 // 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. | 139 // object yet. We'll do it later in ApplyBlock(), on the FILE thread. |
140 } | 140 } |
141 | 141 |
142 void PowerSaveBlocker::Delegate::Init() { | 142 void PowerSaveBlockerImpl::Delegate::Init() { |
143 base::AutoLock lock(lock_); | 143 base::AutoLock lock(lock_); |
144 DCHECK(!enqueue_apply_); | 144 DCHECK(!enqueue_apply_); |
145 enqueue_apply_ = true; | 145 enqueue_apply_ = true; |
146 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 146 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
147 base::Bind(&Delegate::InitOnUIThread, this)); | 147 base::Bind(&Delegate::InitOnUIThread, this)); |
148 } | 148 } |
149 | 149 |
150 void PowerSaveBlocker::Delegate::CleanUp() { | 150 void PowerSaveBlockerImpl::Delegate::CleanUp() { |
151 base::AutoLock lock(lock_); | 151 base::AutoLock lock(lock_); |
152 if (enqueue_apply_) { | 152 if (enqueue_apply_) { |
153 // If a call to ApplyBlock() has not yet been enqueued because we are still | 153 // 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 | 154 // 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. | 155 // remove the block because we haven't even applied it yet. |
156 enqueue_apply_ = false; | 156 enqueue_apply_ = false; |
157 } else if (api_ != NO_API) { | 157 } else if (api_ != NO_API) { |
158 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 158 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
159 base::Bind(&Delegate::RemoveBlock, this, api_)); | 159 base::Bind(&Delegate::RemoveBlock, this, api_)); |
160 } | 160 } |
161 } | 161 } |
162 | 162 |
163 void PowerSaveBlocker::Delegate::InitOnUIThread() { | 163 void PowerSaveBlockerImpl::Delegate::InitOnUIThread() { |
164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
165 base::AutoLock lock(lock_); | 165 base::AutoLock lock(lock_); |
166 api_ = SelectAPI(); | 166 api_ = SelectAPI(); |
167 if (enqueue_apply_ && api_ != NO_API) { | 167 if (enqueue_apply_ && api_ != NO_API) { |
168 // The thread we use here becomes the origin and D-Bus thread for the D-Bus | 168 // 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 | 169 // 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. | 170 // must be a thread that allows I/O operations, so we use the FILE thread. |
171 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 171 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
172 base::Bind(&Delegate::ApplyBlock, this, api_)); | 172 base::Bind(&Delegate::ApplyBlock, this, api_)); |
173 } | 173 } |
174 enqueue_apply_ = false; | 174 enqueue_apply_ = false; |
175 } | 175 } |
176 | 176 |
177 void PowerSaveBlocker::Delegate::ApplyBlock(DBusAPI api) { | 177 void PowerSaveBlockerImpl::Delegate::ApplyBlock(DBusAPI api) { |
178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
179 DCHECK(!bus_.get()); // ApplyBlock() should only be called once. | 179 DCHECK(!bus_.get()); // ApplyBlock() should only be called once. |
180 | 180 |
181 dbus::Bus::Options options; | 181 dbus::Bus::Options options; |
182 options.bus_type = dbus::Bus::SESSION; | 182 options.bus_type = dbus::Bus::SESSION; |
183 options.connection_type = dbus::Bus::PRIVATE; | 183 options.connection_type = dbus::Bus::PRIVATE; |
184 bus_ = new dbus::Bus(options); | 184 bus_ = new dbus::Bus(options); |
185 | 185 |
186 scoped_refptr<dbus::ObjectProxy> object_proxy; | 186 scoped_refptr<dbus::ObjectProxy> object_proxy; |
187 scoped_ptr<dbus::MethodCall> method_call; | 187 scoped_ptr<dbus::MethodCall> method_call; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 // this request. It should be used as an argument to Uninhibit() | 247 // this request. It should be used as an argument to Uninhibit() |
248 // in order to remove the request. | 248 // in order to remove the request. |
249 dbus::MessageReader message_reader(response.get()); | 249 dbus::MessageReader message_reader(response.get()); |
250 if (!message_reader.PopUint32(&inhibit_cookie_)) | 250 if (!message_reader.PopUint32(&inhibit_cookie_)) |
251 LOG(ERROR) << "Invalid Inhibit() response: " << response->ToString(); | 251 LOG(ERROR) << "Invalid Inhibit() response: " << response->ToString(); |
252 } else { | 252 } else { |
253 LOG(ERROR) << "No response to Inhibit() request!"; | 253 LOG(ERROR) << "No response to Inhibit() request!"; |
254 } | 254 } |
255 } | 255 } |
256 | 256 |
257 void PowerSaveBlocker::Delegate::RemoveBlock(DBusAPI api) { | 257 void PowerSaveBlockerImpl::Delegate::RemoveBlock(DBusAPI api) { |
258 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 258 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
259 DCHECK(bus_.get()); // RemoveBlock() should only be called once. | 259 DCHECK(bus_.get()); // RemoveBlock() should only be called once. |
260 | 260 |
261 scoped_refptr<dbus::ObjectProxy> object_proxy; | 261 scoped_refptr<dbus::ObjectProxy> object_proxy; |
262 scoped_ptr<dbus::MethodCall> method_call; | 262 scoped_ptr<dbus::MethodCall> method_call; |
263 | 263 |
264 switch (api) { | 264 switch (api) { |
265 case NO_API: | 265 case NO_API: |
266 NOTREACHED(); // We should never call this method with this value. | 266 NOTREACHED(); // We should never call this method with this value. |
267 return; | 267 return; |
(...skipping 21 matching lines...) Expand all Loading... |
289 LOG(ERROR) << "No response to Uninhibit() request!"; | 289 LOG(ERROR) << "No response to Uninhibit() request!"; |
290 // We don't care about checking the result. We assume it works; we can't | 290 // 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. | 291 // really do anything about it anyway if it fails. |
292 inhibit_cookie_ = 0; | 292 inhibit_cookie_ = 0; |
293 | 293 |
294 bus_->ShutdownAndBlock(); | 294 bus_->ShutdownAndBlock(); |
295 bus_ = NULL; | 295 bus_ = NULL; |
296 } | 296 } |
297 | 297 |
298 // static | 298 // static |
299 bool PowerSaveBlocker::Delegate::DPMSEnabled() { | 299 bool PowerSaveBlockerImpl::Delegate::DPMSEnabled() { |
300 Display* display = base::MessagePumpForUI::GetDefaultXDisplay(); | 300 Display* display = base::MessagePumpForUI::GetDefaultXDisplay(); |
301 BOOL enabled = false; | 301 BOOL enabled = false; |
302 int dummy; | 302 int dummy; |
303 if (DPMSQueryExtension(display, &dummy, &dummy) && DPMSCapable(display)) { | 303 if (DPMSQueryExtension(display, &dummy, &dummy) && DPMSCapable(display)) { |
304 CARD16 state; | 304 CARD16 state; |
305 DPMSInfo(display, &state, &enabled); | 305 DPMSInfo(display, &state, &enabled); |
306 } | 306 } |
307 return enabled; | 307 return enabled; |
308 } | 308 } |
309 | 309 |
310 // static | 310 // static |
311 DBusAPI PowerSaveBlocker::Delegate::SelectAPI() { | 311 DBusAPI PowerSaveBlockerImpl::Delegate::SelectAPI() { |
312 scoped_ptr<base::Environment> env(base::Environment::Create()); | 312 scoped_ptr<base::Environment> env(base::Environment::Create()); |
313 switch (base::nix::GetDesktopEnvironment(env.get())) { | 313 switch (base::nix::GetDesktopEnvironment(env.get())) { |
314 case base::nix::DESKTOP_ENVIRONMENT_GNOME: | 314 case base::nix::DESKTOP_ENVIRONMENT_GNOME: |
315 case base::nix::DESKTOP_ENVIRONMENT_UNITY: | 315 case base::nix::DESKTOP_ENVIRONMENT_UNITY: |
316 if (DPMSEnabled()) | 316 if (DPMSEnabled()) |
317 return GNOME_API; | 317 return GNOME_API; |
318 break; | 318 break; |
319 case base::nix::DESKTOP_ENVIRONMENT_XFCE: | 319 case base::nix::DESKTOP_ENVIRONMENT_XFCE: |
320 case base::nix::DESKTOP_ENVIRONMENT_KDE4: | 320 case base::nix::DESKTOP_ENVIRONMENT_KDE4: |
321 if (DPMSEnabled()) | 321 if (DPMSEnabled()) |
322 return FREEDESKTOP_API; | 322 return FREEDESKTOP_API; |
323 break; | 323 break; |
324 case base::nix::DESKTOP_ENVIRONMENT_KDE3: | 324 case base::nix::DESKTOP_ENVIRONMENT_KDE3: |
325 case base::nix::DESKTOP_ENVIRONMENT_OTHER: | 325 case base::nix::DESKTOP_ENVIRONMENT_OTHER: |
326 // Not supported. | 326 // Not supported. |
327 break; | 327 break; |
328 } | 328 } |
329 return NO_API; | 329 return NO_API; |
330 } | 330 } |
331 | 331 |
332 PowerSaveBlocker::PowerSaveBlocker( | 332 PowerSaveBlockerImpl::PowerSaveBlockerImpl( |
333 PowerSaveBlockerType type, const std::string& reason) | 333 PowerSaveBlockerType type, const std::string& reason) |
334 : delegate_(new Delegate(type, reason)) { | 334 : delegate_(new Delegate(type, reason)) { |
335 delegate_->Init(); | 335 delegate_->Init(); |
336 } | 336 } |
337 | 337 |
338 PowerSaveBlocker::~PowerSaveBlocker() { | 338 PowerSaveBlockerImpl::~PowerSaveBlockerImpl() { |
339 delegate_->CleanUp(); | 339 delegate_->CleanUp(); |
340 } | 340 } |
341 | 341 |
342 } // namespace content | 342 } // namespace content |
OLD | NEW |