| Index: content/browser/power_save_blocker_win.cc
|
| diff --git a/content/browser/power_save_blocker_win.cc b/content/browser/power_save_blocker_win.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e9650a5cc1f634eb827387d6828e81444e0c5fcb
|
| --- /dev/null
|
| +++ b/content/browser/power_save_blocker_win.cc
|
| @@ -0,0 +1,160 @@
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include <windows.h>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/logging.h"
|
| +#include "base/macros.h"
|
| +#include "base/strings/utf_string_conversions.h"
|
| +#include "base/win/scoped_handle.h"
|
| +#include "base/win/windows_version.h"
|
| +#include "content/browser/power_save_blocker_impl.h"
|
| +
|
| +namespace content {
|
| +namespace {
|
| +
|
| +int g_blocker_count[2];
|
| +
|
| +HANDLE CreatePowerRequest(POWER_REQUEST_TYPE type,
|
| + const std::string& description) {
|
| + if (type == PowerRequestExecutionRequired &&
|
| + base::win::GetVersion() < base::win::VERSION_WIN8) {
|
| + return INVALID_HANDLE_VALUE;
|
| + }
|
| +
|
| + base::string16 wide_description = base::ASCIIToUTF16(description);
|
| + REASON_CONTEXT context = {0};
|
| + context.Version = POWER_REQUEST_CONTEXT_VERSION;
|
| + context.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
|
| + context.Reason.SimpleReasonString =
|
| + const_cast<wchar_t*>(wide_description.c_str());
|
| +
|
| + base::win::ScopedHandle handle(::PowerCreateRequest(&context));
|
| + if (!handle.IsValid())
|
| + return INVALID_HANDLE_VALUE;
|
| +
|
| + if (::PowerSetRequest(handle.Get(), type))
|
| + return handle.Take();
|
| +
|
| + // Something went wrong.
|
| + return INVALID_HANDLE_VALUE;
|
| +}
|
| +
|
| +// Takes ownership of the |handle|.
|
| +void DeletePowerRequest(POWER_REQUEST_TYPE type, HANDLE handle) {
|
| + base::win::ScopedHandle request_handle(handle);
|
| + if (!request_handle.IsValid())
|
| + return;
|
| +
|
| + if (type == PowerRequestExecutionRequired &&
|
| + base::win::GetVersion() < base::win::VERSION_WIN8) {
|
| + return;
|
| + }
|
| +
|
| + BOOL success = ::PowerClearRequest(request_handle.Get(), type);
|
| + DCHECK(success);
|
| +}
|
| +
|
| +void ApplySimpleBlock(PowerSaveBlocker::PowerSaveBlockerType type,
|
| + int delta) {
|
| + g_blocker_count[type] += delta;
|
| + DCHECK_GE(g_blocker_count[type], 0);
|
| +
|
| + if (g_blocker_count[type] > 1)
|
| + return;
|
| +
|
| + DWORD this_flag = 0;
|
| + if (type == PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension)
|
| + this_flag |= ES_SYSTEM_REQUIRED;
|
| + else
|
| + this_flag |= ES_DISPLAY_REQUIRED;
|
| +
|
| + DCHECK(this_flag);
|
| +
|
| + static DWORD flags = ES_CONTINUOUS;
|
| + if (!g_blocker_count[type])
|
| + flags &= ~this_flag;
|
| + else
|
| + flags |= this_flag;
|
| +
|
| + SetThreadExecutionState(flags);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +class PowerSaveBlockerImpl::Delegate
|
| + : public base::RefCountedThreadSafe<PowerSaveBlockerImpl::Delegate> {
|
| + public:
|
| + Delegate(PowerSaveBlockerType type,
|
| + const std::string& description,
|
| + scoped_refptr<base::SequencedTaskRunner> ui_task_runner)
|
| + : type_(type),
|
| + description_(description),
|
| + ui_task_runner_(ui_task_runner) {}
|
| +
|
| + // Does the actual work to apply or remove the desired power save block.
|
| + void ApplyBlock();
|
| + void RemoveBlock();
|
| +
|
| + // Returns the equivalent POWER_REQUEST_TYPE for this request.
|
| + POWER_REQUEST_TYPE RequestType();
|
| +
|
| + private:
|
| + friend class base::RefCountedThreadSafe<Delegate>;
|
| + ~Delegate() {}
|
| +
|
| + PowerSaveBlockerType type_;
|
| + const std::string description_;
|
| + base::win::ScopedHandle handle_;
|
| + scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(Delegate);
|
| +};
|
| +
|
| +void PowerSaveBlockerImpl::Delegate::ApplyBlock() {
|
| + DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
|
| + if (base::win::GetVersion() < base::win::VERSION_WIN7)
|
| + return ApplySimpleBlock(type_, 1);
|
| +
|
| + handle_.Set(CreatePowerRequest(RequestType(), description_));
|
| +}
|
| +
|
| +void PowerSaveBlockerImpl::Delegate::RemoveBlock() {
|
| + DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
|
| + if (base::win::GetVersion() < base::win::VERSION_WIN7)
|
| + return ApplySimpleBlock(type_, -1);
|
| +
|
| + DeletePowerRequest(RequestType(), handle_.Take());
|
| +}
|
| +
|
| +POWER_REQUEST_TYPE PowerSaveBlockerImpl::Delegate::RequestType() {
|
| + if (type_ == kPowerSaveBlockPreventDisplaySleep)
|
| + return PowerRequestDisplayRequired;
|
| +
|
| + if (base::win::GetVersion() < base::win::VERSION_WIN8)
|
| + return PowerRequestSystemRequired;
|
| +
|
| + return PowerRequestExecutionRequired;
|
| +}
|
| +
|
| +PowerSaveBlockerImpl::PowerSaveBlockerImpl(
|
| + PowerSaveBlockerType type,
|
| + Reason reason,
|
| + const std::string& description,
|
| + scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
|
| + scoped_refptr<base::SingleThreadTaskRunner> blocking_task_runner)
|
| + : delegate_(new Delegate(type, description, ui_task_runner)),
|
| + ui_task_runner_(ui_task_runner),
|
| + blocking_task_runner_(blocking_task_runner) {
|
| + ui_task_runner_->PostTask(FROM_HERE,
|
| + base::Bind(&Delegate::ApplyBlock, delegate_));
|
| +}
|
| +
|
| +PowerSaveBlockerImpl::~PowerSaveBlockerImpl() {
|
| + ui_task_runner_->PostTask(FROM_HERE,
|
| + base::Bind(&Delegate::RemoveBlock, delegate_));
|
| +}
|
| +
|
| +} // namespace content
|
|
|