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. 4 5#include "chrome/browser/ui/views/elevation_icon_setter.h" 6 7#include "base/task_runner_util.h" 8#include "content/public/browser/browser_thread.h" 9#include "ui/views/controls/button/label_button.h" 10 11#if defined(OS_WIN) 12#include <windows.h> 13#include <shellapi.h> 14#include "base/win/win_util.h" 15#include "base/win/windows_version.h" 16#include "ui/gfx/icon_util.h" 17#endif 18 19 20// Helpers -------------------------------------------------------------------- 21 22namespace { 23 24scoped_ptr<SkBitmap> GetElevationIcon() { 25 scoped_ptr<SkBitmap> icon; 26#if defined(OS_WIN) 27 if ((base::win::GetVersion() < base::win::VERSION_VISTA) || 28 !base::win::UserAccountControlIsEnabled()) 29 return icon.Pass(); 30 31 SHSTOCKICONINFO icon_info = { sizeof(SHSTOCKICONINFO) }; 32 typedef HRESULT (STDAPICALLTYPE *GetStockIconInfo)(SHSTOCKICONID, 33 UINT, 34 SHSTOCKICONINFO*); 35 // Even with the runtime guard above, we have to use GetProcAddress() 36 // here, because otherwise the loader will try to resolve the function 37 // address on startup, which will break on XP. 38 GetStockIconInfo func = reinterpret_cast<GetStockIconInfo>( 39 GetProcAddress(GetModuleHandle(L"shell32.dll"), "SHGetStockIconInfo")); 40 // TODO(pkasting): Run on a background thread since this call spins a nested 41 // message loop. 42 if (FAILED((*func)(SIID_SHIELD, SHGSI_ICON | SHGSI_SMALLICON, &icon_info))) 43 return icon.Pass(); 44 45 icon.reset(IconUtil::CreateSkBitmapFromHICON( 46 icon_info.hIcon, 47 gfx::Size(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)))); 48 DestroyIcon(icon_info.hIcon); 49#endif 50 return icon.Pass(); 51} 52 53} // namespace 54 55 56// ElevationIconSetter -------------------------------------------------------- 57 58ElevationIconSetter::ElevationIconSetter(views::LabelButton* button) 59 : button_(button), 60 weak_factory_(this) { 61 base::PostTaskAndReplyWithResult( 62 content::BrowserThread::GetBlockingPool(), 63 FROM_HERE, 64 base::Bind(&GetElevationIcon), 65 base::Bind(&ElevationIconSetter::SetButtonIcon, 66 weak_factory_.GetWeakPtr())); 67} 68 69ElevationIconSetter::~ElevationIconSetter() { 70} 71 72void ElevationIconSetter::SetButtonIcon(scoped_ptr<SkBitmap> icon) { 73 if (icon) { 74 button_->SetImage(views::Button::STATE_NORMAL, 75 gfx::ImageSkia::CreateFrom1xBitmap(*icon)); 76 button_->SizeToPreferredSize(); 77 if (button_->parent()) 78 button_->parent()->Layout(); 79 } 80} 81