File: elevation_icon_setter.cc

package info (click to toggle)
chromium-browser 70.0.3538.110-1~deb9u1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 1,619,476 kB
  • sloc: cpp: 13,024,755; ansic: 1,349,823; python: 916,672; xml: 314,489; java: 280,047; asm: 276,936; perl: 75,771; objc: 66,634; sh: 45,860; cs: 28,354; php: 11,064; makefile: 10,911; yacc: 9,109; tcl: 8,403; ruby: 4,065; lex: 1,779; pascal: 1,411; lisp: 1,055; awk: 41; jsp: 39; sed: 17; sql: 3
file content (94 lines) | stat: -rw-r--r-- 3,226 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// Copyright 2014 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 "chrome/browser/ui/views/elevation_icon_setter.h"

#include "base/callback.h"
#include "base/task/post_task.h"
#include "build/build_config.h"
#include "ui/views/controls/button/label_button.h"

#if defined(OS_WIN)
#include <windows.h>
#include <shellapi.h>

#include "base/task_runner_util.h"
#include "base/win/win_util.h"
#include "ui/display/win/dpi.h"
#include "ui/gfx/icon_util.h"
#endif


// Helpers --------------------------------------------------------------------

namespace {

#if defined(OS_WIN)
SkBitmap GetElevationIcon() {
  if (!base::win::UserAccountControlIsEnabled())
    return SkBitmap();

  SHSTOCKICONINFO icon_info = { sizeof(SHSTOCKICONINFO) };
  typedef HRESULT (STDAPICALLTYPE *GetStockIconInfo)(SHSTOCKICONID,
                                                     UINT,
                                                     SHSTOCKICONINFO*);
  // Even with the runtime guard above, we have to use GetProcAddress()
  // here, because otherwise the loader will try to resolve the function
  // address on startup, which will break on XP.
  GetStockIconInfo func = reinterpret_cast<GetStockIconInfo>(
      GetProcAddress(GetModuleHandle(L"shell32.dll"), "SHGetStockIconInfo"));
  // TODO(pkasting): Run on a background thread since this call spins a nested
  // message loop.
  if (FAILED((*func)(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), weak_factory_(this) {
#if defined(OS_WIN)
  base::PostTaskAndReplyWithResult(
      base::CreateCOMSTATaskRunnerWithTraits(
          {base::MayBlock(), base::TaskPriority::USER_BLOCKING})
          .get(),
      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 defined(OS_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_->SetImage(
        views::Button::STATE_NORMAL,
        gfx::ImageSkia(gfx::ImageSkiaRep(icon, device_scale_factor)));
    button_->SizeToPreferredSize();
    if (button_->parent())
      button_->parent()->Layout();
    if (!callback.is_null())
      std::move(callback).Run();
  }
}