blob: 6d2841146ba1d7be1fac219ff419203c63c86818 [file] [log] [blame]
[email protected]92269382012-03-03 09:00:081// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]36e93a772009-10-23 04:18:052// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]2b67216b2013-01-15 06:25:175#include "content/browser/power_save_blocker_impl.h"
[email protected]36e93a772009-10-23 04:18:056
7#include <windows.h>
8
[email protected]92269382012-03-03 09:00:089#include "base/logging.h"
[email protected]74ebfb12013-06-07 20:48:0010#include "base/strings/utf_string_conversions.h"
[email protected]5dede9472012-06-06 00:23:5711#include "base/win/scoped_handle.h"
12#include "base/win/windows_version.h"
[email protected]c38831a12011-10-28 12:44:4913#include "content/public/browser/browser_thread.h"
[email protected]36e93a772009-10-23 04:18:0514
[email protected]46488322012-10-30 03:22:2015namespace content {
[email protected]5dede9472012-06-06 00:23:5716namespace {
17
18int g_blocker_count[2];
19
deratf3c302a2015-02-23 18:33:0320HANDLE CreatePowerRequest(POWER_REQUEST_TYPE type,
21 const std::string& description) {
[email protected]5dede9472012-06-06 00:23:5722 typedef HANDLE (WINAPI* PowerCreateRequestPtr)(PREASON_CONTEXT);
23 typedef BOOL (WINAPI* PowerSetRequestPtr)(HANDLE, POWER_REQUEST_TYPE);
24
25 if (type == PowerRequestExecutionRequired &&
26 base::win::GetVersion() < base::win::VERSION_WIN8) {
27 return INVALID_HANDLE_VALUE;
28 }
29
30 static PowerCreateRequestPtr PowerCreateRequestFn = NULL;
31 static PowerSetRequestPtr PowerSetRequestFn = NULL;
32
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"));
39
40 if (!PowerCreateRequestFn || !PowerSetRequestFn)
41 return INVALID_HANDLE_VALUE;
42 }
deratf3c302a2015-02-23 18:33:0343 base::string16 wide_description = base::ASCIIToUTF16(description);
[email protected]5dede9472012-06-06 00:23:5744 REASON_CONTEXT context = {0};
45 context.Version = POWER_REQUEST_CONTEXT_VERSION;
46 context.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
deratf3c302a2015-02-23 18:33:0347 context.Reason.SimpleReasonString =
48 const_cast<wchar_t*>(wide_description.c_str());
[email protected]5dede9472012-06-06 00:23:5749
50 base::win::ScopedHandle handle(PowerCreateRequestFn(&context));
51 if (!handle.IsValid())
52 return INVALID_HANDLE_VALUE;
53
rvargasff9eea52014-09-25 01:04:1954 if (PowerSetRequestFn(handle.Get(), type))
[email protected]5dede9472012-06-06 00:23:5755 return handle.Take();
56
57 // Something went wrong.
58 return INVALID_HANDLE_VALUE;
59}
60
61// Takes ownership of the |handle|.
62void DeletePowerRequest(POWER_REQUEST_TYPE type, HANDLE handle) {
63 base::win::ScopedHandle request_handle(handle);
64 if (!request_handle.IsValid())
65 return;
66
67 if (type == PowerRequestExecutionRequired &&
68 base::win::GetVersion() < base::win::VERSION_WIN8) {
69 return;
70 }
71
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"));
77
78 if (!PowerClearRequestFn)
79 return;
80
rvargasff9eea52014-09-25 01:04:1981 BOOL success = PowerClearRequestFn(request_handle.Get(), type);
[email protected]5dede9472012-06-06 00:23:5782 DCHECK(success);
83}
84
[email protected]46488322012-10-30 03:22:2085void ApplySimpleBlock(PowerSaveBlocker::PowerSaveBlockerType type,
[email protected]5dede9472012-06-06 00:23:5786 int delta) {
87 g_blocker_count[type] += delta;
88 DCHECK_GE(g_blocker_count[type], 0);
89
90 if (g_blocker_count[type] > 1)
91 return;
92
93 DWORD this_flag = 0;
[email protected]46488322012-10-30 03:22:2094 if (type == PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension)
[email protected]5dede9472012-06-06 00:23:5795 this_flag |= ES_SYSTEM_REQUIRED;
96 else
97 this_flag |= ES_DISPLAY_REQUIRED;
98
99 DCHECK(this_flag);
100
101 static DWORD flags = ES_CONTINUOUS;
102 if (!g_blocker_count[type])
103 flags &= ~this_flag;
104 else
105 flags |= this_flag;
106
107 SetThreadExecutionState(flags);
108}
109
[email protected]2b67216b2013-01-15 06:25:17110} // namespace
[email protected]5dede9472012-06-06 00:23:57111
[email protected]2b67216b2013-01-15 06:25:17112class PowerSaveBlockerImpl::Delegate
113 : public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> {
[email protected]5dede9472012-06-06 00:23:57114 public:
deratf3c302a2015-02-23 18:33:03115 Delegate(PowerSaveBlockerType type, const std::string& description)
116 : type_(type), description_(description) {}
[email protected]5dede9472012-06-06 00:23:57117
118 // Does the actual work to apply or remove the desired power save block.
119 void ApplyBlock();
120 void RemoveBlock();
121
122 // Returns the equivalent POWER_REQUEST_TYPE for this request.
123 POWER_REQUEST_TYPE RequestType();
124
125 private:
[email protected]6b55aec2012-06-11 18:02:03126 friend class base::RefCountedThreadSafe<Delegate>;
[email protected]5dede9472012-06-06 00:23:57127 ~Delegate() {}
128
129 PowerSaveBlockerType type_;
deratf3c302a2015-02-23 18:33:03130 const std::string description_;
[email protected]5dede9472012-06-06 00:23:57131 base::win::ScopedHandle handle_;
132
133 DISALLOW_COPY_AND_ASSIGN(Delegate);
134};
135
[email protected]2b67216b2013-01-15 06:25:17136void PowerSaveBlockerImpl::Delegate::ApplyBlock() {
mostynb4c27d042015-03-18 21:47:47137 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]8902dac2012-06-07 21:59:14138 if (base::win::GetVersion() < base::win::VERSION_WIN7)
[email protected]5dede9472012-06-06 00:23:57139 return ApplySimpleBlock(type_, 1);
140
deratf3c302a2015-02-23 18:33:03141 handle_.Set(CreatePowerRequest(RequestType(), description_));
[email protected]5dede9472012-06-06 00:23:57142}
143
[email protected]2b67216b2013-01-15 06:25:17144void PowerSaveBlockerImpl::Delegate::RemoveBlock() {
mostynb4c27d042015-03-18 21:47:47145 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]8902dac2012-06-07 21:59:14146 if (base::win::GetVersion() < base::win::VERSION_WIN7)
[email protected]5dede9472012-06-06 00:23:57147 return ApplySimpleBlock(type_, -1);
148
149 DeletePowerRequest(RequestType(), handle_.Take());
150}
151
[email protected]2b67216b2013-01-15 06:25:17152POWER_REQUEST_TYPE PowerSaveBlockerImpl::Delegate::RequestType() {
[email protected]5dede9472012-06-06 00:23:57153 if (type_ == kPowerSaveBlockPreventDisplaySleep)
154 return PowerRequestDisplayRequired;
155
[email protected]8902dac2012-06-07 21:59:14156 if (base::win::GetVersion() < base::win::VERSION_WIN8)
157 return PowerRequestSystemRequired;
158
[email protected]5dede9472012-06-06 00:23:57159 return PowerRequestExecutionRequired;
160}
161
[email protected]2b67216b2013-01-15 06:25:17162PowerSaveBlockerImpl::PowerSaveBlockerImpl(PowerSaveBlockerType type,
deratf3c302a2015-02-23 18:33:03163 Reason reason,
164 const std::string& description)
165 : delegate_(new Delegate(type, description)) {
[email protected]5dede9472012-06-06 00:23:57166 BrowserThread::PostTask(
167 BrowserThread::UI, FROM_HERE,
168 base::Bind(&Delegate::ApplyBlock, delegate_));
169}
170
[email protected]2b67216b2013-01-15 06:25:17171PowerSaveBlockerImpl::~PowerSaveBlockerImpl() {
[email protected]5dede9472012-06-06 00:23:57172 BrowserThread::PostTask(
173 BrowserThread::UI, FROM_HERE,
174 base::Bind(&Delegate::RemoveBlock, delegate_));
175}
176
177} // namespace content