15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved.
25c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Use of this source code is governed by a BSD-style license that can be
35c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// found in the LICENSE file.
45c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/ui/views/elevation_icon_setter.h"
65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/task_runner_util.h"
85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/public/browser/browser_thread.h"
95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/views/controls/button/label_button.h"
105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#if defined(OS_WIN)
125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <windows.h>
135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <shellapi.h>
145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/win/win_util.h"
155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/win/windows_version.h"
165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/gfx/icon_util.h"
175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif
185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Helpers --------------------------------------------------------------------
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace {
235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuscoped_ptr<SkBitmap> GetElevationIcon() {
255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<SkBitmap> icon;
265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#if defined(OS_WIN)
275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if ((base::win::GetVersion() < base::win::VERSION_VISTA) ||
285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      !base::win::UserAccountControlIsEnabled())
295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return icon.Pass();
305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  SHSTOCKICONINFO icon_info = { sizeof(SHSTOCKICONINFO) };
325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  typedef HRESULT (STDAPICALLTYPE *GetStockIconInfo)(SHSTOCKICONID,
335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                     UINT,
345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                     SHSTOCKICONINFO*);
355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Even with the runtime guard above, we have to use GetProcAddress()
365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // here, because otherwise the loader will try to resolve the function
375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // address on startup, which will break on XP.
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  GetStockIconInfo func = reinterpret_cast<GetStockIconInfo>(
395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      GetProcAddress(GetModuleHandle(L"shell32.dll"), "SHGetStockIconInfo"));
405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // TODO(pkasting): Run on a background thread since this call spins a nested
415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // message loop.
425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (FAILED((*func)(SIID_SHIELD, SHGSI_ICON | SHGSI_SMALLICON, &icon_info)))
435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return icon.Pass();
445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  icon.reset(IconUtil::CreateSkBitmapFromHICON(
465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      icon_info.hIcon,
475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      gfx::Size(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON))));
485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DestroyIcon(icon_info.hIcon);
495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif
505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return icon.Pass();
515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}  // namespace
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// ElevationIconSetter --------------------------------------------------------
575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuElevationIconSetter::ElevationIconSetter(views::LabelButton* button)
595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    : button_(button),
605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      weak_factory_(this) {
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::PostTaskAndReplyWithResult(
625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      content::BrowserThread::GetBlockingPool(),
635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      FROM_HERE,
645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::Bind(&GetElevationIcon),
655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      base::Bind(&ElevationIconSetter::SetButtonIcon,
665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 weak_factory_.GetWeakPtr()));
675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuElevationIconSetter::~ElevationIconSetter() {
705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid ElevationIconSetter::SetButtonIcon(scoped_ptr<SkBitmap> icon) {
735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (icon) {
745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    button_->SetImage(views::Button::STATE_NORMAL,
755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                      gfx::ImageSkia::CreateFrom1xBitmap(*icon));
765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    button_->SizeToPreferredSize();
775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (button_->parent())
785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      button_->parent()->Layout();
795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
81