Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / views / elevation_icon_setter.cc
blob356c71d22238934e59b3620e1226ad8c43872369
1 // Copyright 2014 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 "chrome/browser/ui/views/elevation_icon_setter.h"
7 #include "base/callback.h"
8 #include "base/task_runner_util.h"
9 #include "content/public/browser/browser_thread.h"
10 #include "ui/views/controls/button/label_button.h"
12 #if defined(OS_WIN)
13 #include <windows.h>
14 #include <shellapi.h>
15 #include "base/win/win_util.h"
16 #include "base/win/windows_version.h"
17 #include "ui/gfx/icon_util.h"
18 #include "ui/gfx/win/dpi.h"
19 #endif
22 // Helpers --------------------------------------------------------------------
24 namespace {
26 scoped_ptr<SkBitmap> GetElevationIcon() {
27 scoped_ptr<SkBitmap> icon;
28 #if defined(OS_WIN)
29 if ((base::win::GetVersion() < base::win::VERSION_VISTA) ||
30 !base::win::UserAccountControlIsEnabled())
31 return icon.Pass();
33 SHSTOCKICONINFO icon_info = { sizeof(SHSTOCKICONINFO) };
34 typedef HRESULT (STDAPICALLTYPE *GetStockIconInfo)(SHSTOCKICONID,
35 UINT,
36 SHSTOCKICONINFO*);
37 // Even with the runtime guard above, we have to use GetProcAddress()
38 // here, because otherwise the loader will try to resolve the function
39 // address on startup, which will break on XP.
40 GetStockIconInfo func = reinterpret_cast<GetStockIconInfo>(
41 GetProcAddress(GetModuleHandle(L"shell32.dll"), "SHGetStockIconInfo"));
42 // TODO(pkasting): Run on a background thread since this call spins a nested
43 // message loop.
44 if (FAILED((*func)(SIID_SHIELD, SHGSI_ICON | SHGSI_SMALLICON, &icon_info)))
45 return icon.Pass();
47 icon.reset(IconUtil::CreateSkBitmapFromHICON(
48 icon_info.hIcon,
49 gfx::Size(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON))));
50 DestroyIcon(icon_info.hIcon);
51 #endif
52 return icon.Pass();
55 } // namespace
58 // ElevationIconSetter --------------------------------------------------------
60 ElevationIconSetter::ElevationIconSetter(views::LabelButton* button,
61 const base::Closure& callback)
62 : button_(button),
63 weak_factory_(this) {
64 base::PostTaskAndReplyWithResult(
65 content::BrowserThread::GetBlockingPool(),
66 FROM_HERE,
67 base::Bind(&GetElevationIcon),
68 base::Bind(&ElevationIconSetter::SetButtonIcon,
69 weak_factory_.GetWeakPtr(),
70 callback));
73 ElevationIconSetter::~ElevationIconSetter() {
76 void ElevationIconSetter::SetButtonIcon(const base::Closure& callback,
77 scoped_ptr<SkBitmap> icon) {
78 if (icon) {
79 float device_scale_factor = 1.0f;
80 #if defined(OS_WIN)
81 // Windows gives us back a correctly-scaled image for the current DPI, so
82 // mark this image as having been scaled for the current DPI already.
83 device_scale_factor = gfx::GetDPIScale();
84 #endif
85 button_->SetImage(
86 views::Button::STATE_NORMAL,
87 gfx::ImageSkia(gfx::ImageSkiaRep(*icon, device_scale_factor)));
88 button_->SizeToPreferredSize();
89 if (button_->parent())
90 button_->parent()->Layout();
91 if (!callback.is_null())
92 callback.Run();