blob: 4cbecf4447a8957bd066e83dc43f376b32f766f0 [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
[email protected]5dede9472012-06-06 00:23:5720HANDLE 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);
23
24 if (type == PowerRequestExecutionRequired &&
25 base::win::GetVersion() < base::win::VERSION_WIN8) {
26 return INVALID_HANDLE_VALUE;
27 }
28
29 static PowerCreateRequestPtr PowerCreateRequestFn = NULL;
30 static PowerSetRequestPtr PowerSetRequestFn = NULL;
31
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"));
38
39 if (!PowerCreateRequestFn || !PowerSetRequestFn)
40 return INVALID_HANDLE_VALUE;
41 }
[email protected]32956122013-12-25 07:29:2442 base::string16 wide_reason = base::ASCIIToUTF16(reason);
[email protected]5dede9472012-06-06 00:23:5743 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());
47
48 base::win::ScopedHandle handle(PowerCreateRequestFn(&context));
49 if (!handle.IsValid())
50 return INVALID_HANDLE_VALUE;
51
rvargasff9eea52014-09-25 01:04:1952 if (PowerSetRequestFn(handle.Get(), type))
[email protected]5dede9472012-06-06 00:23:5753 return handle.Take();
54
55 // Something went wrong.
56 return INVALID_HANDLE_VALUE;
57}
58
59// Takes ownership of the |handle|.
60void DeletePowerRequest(POWER_REQUEST_TYPE type, HANDLE handle) {
61 base::win::ScopedHandle request_handle(handle);
62 if (!request_handle.IsValid())
63 return;
64
65 if (type == PowerRequestExecutionRequired &&
66 base::win::GetVersion() < base::win::VERSION_WIN8) {
67 return;
68 }
69
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"));
75
76 if (!PowerClearRequestFn)
77 return;
78
rvargasff9eea52014-09-25 01:04:1979 BOOL success = PowerClearRequestFn(request_handle.Get(), type);
[email protected]5dede9472012-06-06 00:23:5780 DCHECK(success);
81}
82
[email protected]46488322012-10-30 03:22:2083void ApplySimpleBlock(PowerSaveBlocker::PowerSaveBlockerType type,
[email protected]5dede9472012-06-06 00:23:5784 int delta) {
85 g_blocker_count[type] += delta;
86 DCHECK_GE(g_blocker_count[type], 0);
87
88 if (g_blocker_count[type] > 1)
89 return;
90
91 DWORD this_flag = 0;
[email protected]46488322012-10-30 03:22:2092 if (type == PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension)
[email protected]5dede9472012-06-06 00:23:5793 this_flag |= ES_SYSTEM_REQUIRED;
94 else
95 this_flag |= ES_DISPLAY_REQUIRED;
96
97 DCHECK(this_flag);
98
99 static DWORD flags = ES_CONTINUOUS;
100 if (!g_blocker_count[type])
101 flags &= ~this_flag;
102 else
103 flags |= this_flag;
104
105 SetThreadExecutionState(flags);
106}
107
[email protected]2b67216b2013-01-15 06:25:17108} // namespace
[email protected]5dede9472012-06-06 00:23:57109
[email protected]2b67216b2013-01-15 06:25:17110class PowerSaveBlockerImpl::Delegate
111 : public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> {
[email protected]5dede9472012-06-06 00:23:57112 public:
113 Delegate(PowerSaveBlockerType type, const std::string& reason)
114 : type_(type), reason_(reason) {}
115
116 // Does the actual work to apply or remove the desired power save block.
117 void ApplyBlock();
118 void RemoveBlock();
119
120 // Returns the equivalent POWER_REQUEST_TYPE for this request.
121 POWER_REQUEST_TYPE RequestType();
122
123 private:
[email protected]6b55aec2012-06-11 18:02:03124 friend class base::RefCountedThreadSafe<Delegate>;
[email protected]5dede9472012-06-06 00:23:57125 ~Delegate() {}
126
127 PowerSaveBlockerType type_;
128 const std::string reason_;
129 base::win::ScopedHandle handle_;
130
131 DISALLOW_COPY_AND_ASSIGN(Delegate);
132};
133
[email protected]2b67216b2013-01-15 06:25:17134void PowerSaveBlockerImpl::Delegate::ApplyBlock() {
[email protected]5dede9472012-06-06 00:23:57135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]8902dac2012-06-07 21:59:14136 if (base::win::GetVersion() < base::win::VERSION_WIN7)
[email protected]5dede9472012-06-06 00:23:57137 return ApplySimpleBlock(type_, 1);
138
139 handle_.Set(CreatePowerRequest(RequestType(), reason_));
140}
141
[email protected]2b67216b2013-01-15 06:25:17142void PowerSaveBlockerImpl::Delegate::RemoveBlock() {
[email protected]5dede9472012-06-06 00:23:57143 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]8902dac2012-06-07 21:59:14144 if (base::win::GetVersion() < base::win::VERSION_WIN7)
[email protected]5dede9472012-06-06 00:23:57145 return ApplySimpleBlock(type_, -1);
146
147 DeletePowerRequest(RequestType(), handle_.Take());
148}
149
[email protected]2b67216b2013-01-15 06:25:17150POWER_REQUEST_TYPE PowerSaveBlockerImpl::Delegate::RequestType() {
[email protected]5dede9472012-06-06 00:23:57151 if (type_ == kPowerSaveBlockPreventDisplaySleep)
152 return PowerRequestDisplayRequired;
153
[email protected]8902dac2012-06-07 21:59:14154 if (base::win::GetVersion() < base::win::VERSION_WIN8)
155 return PowerRequestSystemRequired;
156
[email protected]5dede9472012-06-06 00:23:57157 return PowerRequestExecutionRequired;
158}
159
[email protected]2b67216b2013-01-15 06:25:17160PowerSaveBlockerImpl::PowerSaveBlockerImpl(PowerSaveBlockerType type,
161 const std::string& reason)
[email protected]5dede9472012-06-06 00:23:57162 : delegate_(new Delegate(type, reason)) {
163 BrowserThread::PostTask(
164 BrowserThread::UI, FROM_HERE,
165 base::Bind(&Delegate::ApplyBlock, delegate_));
166}
167
[email protected]2b67216b2013-01-15 06:25:17168PowerSaveBlockerImpl::~PowerSaveBlockerImpl() {
[email protected]5dede9472012-06-06 00:23:57169 BrowserThread::PostTask(
170 BrowserThread::UI, FROM_HERE,
171 base::Bind(&Delegate::RemoveBlock, delegate_));
172}
173
174} // namespace content