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
,
21 const std::string
& description
) {
22 typedef HANDLE (WINAPI
* PowerCreateRequestPtr
)(PREASON_CONTEXT
);
23 typedef BOOL (WINAPI
* PowerSetRequestPtr
)(HANDLE
, POWER_REQUEST_TYPE
);
25 if (type
== PowerRequestExecutionRequired
&&
26 base::win::GetVersion() < base::win::VERSION_WIN8
) {
27 return INVALID_HANDLE_VALUE
;
30 static PowerCreateRequestPtr PowerCreateRequestFn
= NULL
;
31 static PowerSetRequestPtr PowerSetRequestFn
= NULL
;
33 if (!PowerCreateRequestFn
|| !PowerSetRequestFn
) {
34 HMODULE module
= GetModuleHandle(L
"kernel32.dll");
35 PowerCreateRequestFn
= reinterpret_cast<PowerCreateRequestPtr
>(
36 GetProcAddress(module
, "PowerCreateRequest"));
37 PowerSetRequestFn
= reinterpret_cast<PowerSetRequestPtr
>(
38 GetProcAddress(module
, "PowerSetRequest"));
40 if (!PowerCreateRequestFn
|| !PowerSetRequestFn
)
41 return INVALID_HANDLE_VALUE
;
43 base::string16 wide_description
= base::ASCIIToUTF16(description
);
44 REASON_CONTEXT context
= {0};
45 context
.Version
= POWER_REQUEST_CONTEXT_VERSION
;
46 context
.Flags
= POWER_REQUEST_CONTEXT_SIMPLE_STRING
;
47 context
.Reason
.SimpleReasonString
=
48 const_cast<wchar_t*>(wide_description
.c_str());
50 base::win::ScopedHandle
handle(PowerCreateRequestFn(&context
));
51 if (!handle
.IsValid())
52 return INVALID_HANDLE_VALUE
;
54 if (PowerSetRequestFn(handle
.Get(), type
))
57 // Something went wrong.
58 return INVALID_HANDLE_VALUE
;
61 // Takes ownership of the |handle|.
62 void DeletePowerRequest(POWER_REQUEST_TYPE type
, HANDLE handle
) {
63 base::win::ScopedHandle
request_handle(handle
);
64 if (!request_handle
.IsValid())
67 if (type
== PowerRequestExecutionRequired
&&
68 base::win::GetVersion() < base::win::VERSION_WIN8
) {
72 typedef BOOL (WINAPI
* PowerClearRequestPtr
)(HANDLE
, POWER_REQUEST_TYPE
);
73 HMODULE module
= GetModuleHandle(L
"kernel32.dll");
74 PowerClearRequestPtr PowerClearRequestFn
=
75 reinterpret_cast<PowerClearRequestPtr
>(
76 GetProcAddress(module
, "PowerClearRequest"));
78 if (!PowerClearRequestFn
)
81 BOOL success
= PowerClearRequestFn(request_handle
.Get(), type
);
85 void ApplySimpleBlock(PowerSaveBlocker::PowerSaveBlockerType type
,
87 g_blocker_count
[type
] += delta
;
88 DCHECK_GE(g_blocker_count
[type
], 0);
90 if (g_blocker_count
[type
] > 1)
94 if (type
== PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension
)
95 this_flag
|= ES_SYSTEM_REQUIRED
;
97 this_flag
|= ES_DISPLAY_REQUIRED
;
101 static DWORD flags
= ES_CONTINUOUS
;
102 if (!g_blocker_count
[type
])
107 SetThreadExecutionState(flags
);
112 class PowerSaveBlockerImpl::Delegate
113 : public base::RefCountedThreadSafe
<PowerSaveBlockerImpl::Delegate
> {
115 Delegate(PowerSaveBlockerType type
, const std::string
& description
)
116 : type_(type
), description_(description
) {}
118 // Does the actual work to apply or remove the desired power save block.
122 // Returns the equivalent POWER_REQUEST_TYPE for this request.
123 POWER_REQUEST_TYPE
RequestType();
126 friend class base::RefCountedThreadSafe
<Delegate
>;
129 PowerSaveBlockerType type_
;
130 const std::string description_
;
131 base::win::ScopedHandle handle_
;
133 DISALLOW_COPY_AND_ASSIGN(Delegate
);
136 void PowerSaveBlockerImpl::Delegate::ApplyBlock() {
137 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
138 if (base::win::GetVersion() < base::win::VERSION_WIN7
)
139 return ApplySimpleBlock(type_
, 1);
141 handle_
.Set(CreatePowerRequest(RequestType(), description_
));
144 void PowerSaveBlockerImpl::Delegate::RemoveBlock() {
145 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
146 if (base::win::GetVersion() < base::win::VERSION_WIN7
)
147 return ApplySimpleBlock(type_
, -1);
149 DeletePowerRequest(RequestType(), handle_
.Take());
152 POWER_REQUEST_TYPE
PowerSaveBlockerImpl::Delegate::RequestType() {
153 if (type_
== kPowerSaveBlockPreventDisplaySleep
)
154 return PowerRequestDisplayRequired
;
156 if (base::win::GetVersion() < base::win::VERSION_WIN8
)
157 return PowerRequestSystemRequired
;
159 return PowerRequestExecutionRequired
;
162 PowerSaveBlockerImpl::PowerSaveBlockerImpl(PowerSaveBlockerType type
,
164 const std::string
& description
)
165 : delegate_(new Delegate(type
, description
)) {
166 BrowserThread::PostTask(
167 BrowserThread::UI
, FROM_HERE
,
168 base::Bind(&Delegate::ApplyBlock
, delegate_
));
171 PowerSaveBlockerImpl::~PowerSaveBlockerImpl() {
172 BrowserThread::PostTask(
173 BrowserThread::UI
, FROM_HERE
,
174 base::Bind(&Delegate::RemoveBlock
, delegate_
));
177 } // namespace content