blob: 6db19aa3dbc3d7018dde18db97dbe9e142e7e11f [file] [log] [blame]
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/elevation_icon_setter.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/task/thread_pool.h"
#include "build/build_config.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/views/controls/button/label_button.h"
#if BUILDFLAG(IS_WIN)
#include <windows.h>
#include <shellapi.h>
#include "base/win/win_util.h"
#include "ui/display/win/dpi.h"
#include "ui/gfx/icon_util.h"
#endif
// Helpers --------------------------------------------------------------------
namespace {
#if BUILDFLAG(IS_WIN)
SkBitmap GetElevationIcon() {
if (!base::win::UserAccountControlIsEnabled())
return SkBitmap();
SHSTOCKICONINFO icon_info = { sizeof(SHSTOCKICONINFO) };
if (FAILED(SHGetStockIconInfo(SIID_SHIELD, SHGSI_ICON | SHGSI_SMALLICON,
&icon_info)))
return SkBitmap();
SkBitmap icon = IconUtil::CreateSkBitmapFromHICON(
icon_info.hIcon,
gfx::Size(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)));
DestroyIcon(icon_info.hIcon);
return icon;
}
#endif
} // namespace
// ElevationIconSetter --------------------------------------------------------
ElevationIconSetter::ElevationIconSetter(views::LabelButton* button,
base::OnceClosure callback)
: button_(button) {
#if BUILDFLAG(IS_WIN)
base::ThreadPool::CreateCOMSTATaskRunner(
{base::MayBlock(), base::TaskPriority::USER_BLOCKING})
->PostTaskAndReplyWithResult(
FROM_HERE, base::BindOnce(&GetElevationIcon),
base::BindOnce(&ElevationIconSetter::SetButtonIcon,
weak_factory_.GetWeakPtr(), std::move(callback)));
#endif
}
ElevationIconSetter::~ElevationIconSetter() {
}
void ElevationIconSetter::SetButtonIcon(base::OnceClosure callback,
const SkBitmap& icon) {
if (!icon.isNull()) {
float device_scale_factor = 1.0f;
#if BUILDFLAG(IS_WIN)
// Windows gives us back a correctly-scaled image for the current DPI, so
// mark this image as having been scaled for the current DPI already.
device_scale_factor = display::win::GetDPIScale();
#endif
button_->SetImageModel(
views::Button::STATE_NORMAL,
ui::ImageModel::FromImageSkia(
gfx::ImageSkia::CreateFromBitmap(icon, device_scale_factor)));
button_->SizeToPreferredSize();
if (button_->parent())
button_->parent()->DeprecatedLayoutImmediately();
if (!callback.is_null())
std::move(callback).Run();
}
}