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
3 // found in the LICENSE file.
5 #include "content/browser/power_save_blocker_impl.h"
9 #include "base/logging.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/win/scoped_handle.h"
12 #include "base/win/windows_version.h"
13 #include "content/public/browser/browser_thread.h"
18 int g_blocker_count
[2];
20 HANDLE
CreatePowerRequest(POWER_REQUEST_TYPE type
, const std::string
& reason
) {
21 typedef HANDLE (WINAPI
* PowerCreateRequestPtr
)(PREASON_CONTEXT
);
22 typedef BOOL (WINAPI
* PowerSetRequestPtr
)(HANDLE
, POWER_REQUEST_TYPE
);
24 if (type
== PowerRequestExecutionRequired
&&
25 base::win::GetVersion() < base::win::VERSION_WIN8
) {
26 return INVALID_HANDLE_VALUE
;
29 static PowerCreateRequestPtr PowerCreateRequestFn
= NULL
;
30 static PowerSetRequestPtr PowerSetRequestFn
= NULL
;
32 if (!PowerCreateRequestFn
|| !PowerSetRequestFn
) {
33 HMODULE module
= GetModuleHandle(L
"kernel32.dll");
34 PowerCreateRequestFn
= reinterpret_cast<PowerCreateRequestPtr
>(
35 GetProcAddress(module
, "PowerCreateRequest"));
36 PowerSetRequestFn
= reinterpret_cast<PowerSetRequestPtr
>(
37 GetProcAddress(module
, "PowerSetRequest"));
39 if (!PowerCreateRequestFn
|| !PowerSetRequestFn
)
40 return INVALID_HANDLE_VALUE
;
42 base::string16 wide_reason
= base::ASCIIToUTF16(reason
);
43 REASON_CONTEXT context
= {0};
44 context
.Version
= POWER_REQUEST_CONTEXT_VERSION
;
45 context
.Flags
= POWER_REQUEST_CONTEXT_SIMPLE_STRING
;
46 context
.Reason
.SimpleReasonString
= const_cast<wchar_t*>(wide_reason
.c_str());
48 base::win::ScopedHandle
handle(PowerCreateRequestFn(&context
));
49 if (!handle
.IsValid())
50 return INVALID_HANDLE_VALUE
;
52 if (PowerSetRequestFn(handle
, type
))
55 // Something went wrong.
56 return INVALID_HANDLE_VALUE
;
59 // Takes ownership of the |handle|.
60 void DeletePowerRequest(POWER_REQUEST_TYPE type
, HANDLE handle
) {
61 base::win::ScopedHandle
request_handle(handle
);
62 if (!request_handle
.IsValid())
65 if (type
== PowerRequestExecutionRequired
&&
66 base::win::GetVersion() < base::win::VERSION_WIN8
) {
70 typedef BOOL (WINAPI
* PowerClearRequestPtr
)(HANDLE
, POWER_REQUEST_TYPE
);
71 HMODULE module
= GetModuleHandle(L
"kernel32.dll");
72 PowerClearRequestPtr PowerClearRequestFn
=
73 reinterpret_cast<PowerClearRequestPtr
>(
74 GetProcAddress(module
, "PowerClearRequest"));
76 if (!PowerClearRequestFn
)
79 BOOL success
= PowerClearRequestFn(request_handle
, type
);
83 void ApplySimpleBlock(PowerSaveBlocker::PowerSaveBlockerType type
,
85 g_blocker_count
[type
] += delta
;
86 DCHECK_GE(g_blocker_count
[type
], 0);
88 if (g_blocker_count
[type
] > 1)
92 if (type
== PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension
)
93 this_flag
|= ES_SYSTEM_REQUIRED
;
95 this_flag
|= ES_DISPLAY_REQUIRED
;
99 static DWORD flags
= ES_CONTINUOUS
;
100 if (!g_blocker_count
[type
])
105 SetThreadExecutionState(flags
);
110 class PowerSaveBlockerImpl::Delegate
111 : public base::RefCountedThreadSafe
<PowerSaveBlockerImpl::Delegate
> {
113 Delegate(PowerSaveBlockerType type
, const std::string
& reason
)
114 : type_(type
), reason_(reason
) {}
116 // Does the actual work to apply or remove the desired power save block.
120 // Returns the equivalent POWER_REQUEST_TYPE for this request.
121 POWER_REQUEST_TYPE
RequestType();
124 friend class base::RefCountedThreadSafe
<Delegate
>;
127 PowerSaveBlockerType type_
;
128 const std::string reason_
;
129 base::win::ScopedHandle handle_
;
131 DISALLOW_COPY_AND_ASSIGN(Delegate
);
134 void PowerSaveBlockerImpl::Delegate::ApplyBlock() {
135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
136 if (base::win::GetVersion() < base::win::VERSION_WIN7
)
137 return ApplySimpleBlock(type_
, 1);
139 handle_
.Set(CreatePowerRequest(RequestType(), reason_
));
142 void PowerSaveBlockerImpl::Delegate::RemoveBlock() {
143 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
144 if (base::win::GetVersion() < base::win::VERSION_WIN7
)
145 return ApplySimpleBlock(type_
, -1);
147 DeletePowerRequest(RequestType(), handle_
.Take());
150 POWER_REQUEST_TYPE
PowerSaveBlockerImpl::Delegate::RequestType() {
151 if (type_
== kPowerSaveBlockPreventDisplaySleep
)
152 return PowerRequestDisplayRequired
;
154 if (base::win::GetVersion() < base::win::VERSION_WIN8
)
155 return PowerRequestSystemRequired
;
157 return PowerRequestExecutionRequired
;
160 PowerSaveBlockerImpl::PowerSaveBlockerImpl(PowerSaveBlockerType type
,
161 const std::string
& reason
)
162 : delegate_(new Delegate(type
, reason
)) {
163 BrowserThread::PostTask(
164 BrowserThread::UI
, FROM_HERE
,
165 base::Bind(&Delegate::ApplyBlock
, delegate_
));
168 PowerSaveBlockerImpl::~PowerSaveBlockerImpl() {
169 BrowserThread::PostTask(
170 BrowserThread::UI
, FROM_HERE
,
171 base::Bind(&Delegate::RemoveBlock
, delegate_
));
174 } // namespace content