summaryrefslogtreecommitdiff
path: root/chromium/ui/base/win/shell.cc
blob: df90108ac4fb86d451aa63ea37fbd3b57f3a108b (plain)
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright (c) 2012 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 "ui/base/win/shell.h"

#include <dwmapi.h>
#include <shlobj.h>  // Must be before propkey.
#include <propkey.h>
#include <shellapi.h>

#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/native_library.h"
#include "base/strings/string_util.h"
#include "base/win/metro.h"
#include "base/win/scoped_comptr.h"
#include "base/win/win_util.h"
#include "base/win/windows_version.h"
#include "ui/base/ui_base_switches.h"

namespace ui {
namespace win {

namespace {

void SetAppDetailsForWindow(const string16& app_id,
                            const string16& app_icon,
                            const string16& relaunch_command,
                            const string16& relaunch_display_name,
                            HWND hwnd) {
  // This functionality is only available on Win7+. It also doesn't make sense
  // to do this for Chrome Metro.
  if (base::win::GetVersion() < base::win::VERSION_WIN7 ||
      base::win::IsMetroProcess())
    return;
  base::win::ScopedComPtr<IPropertyStore> pps;
  HRESULT result = SHGetPropertyStoreForWindow(
      hwnd, __uuidof(*pps), reinterpret_cast<void**>(pps.Receive()));
  if (S_OK == result) {
    if (!app_id.empty())
      base::win::SetAppIdForPropertyStore(pps, app_id.c_str());
    if (!app_icon.empty()) {
      base::win::SetStringValueForPropertyStore(
          pps, PKEY_AppUserModel_RelaunchIconResource, app_icon.c_str());
    }
    if (!relaunch_command.empty()) {
      base::win::SetStringValueForPropertyStore(
          pps, PKEY_AppUserModel_RelaunchCommand, relaunch_command.c_str());
    }
    if (!relaunch_display_name.empty()) {
      base::win::SetStringValueForPropertyStore(
          pps, PKEY_AppUserModel_RelaunchDisplayNameResource,
          relaunch_display_name.c_str());
    }
  }
}

}  // namespace

// Show the Windows "Open With" dialog box to ask the user to pick an app to
// open the file with.
bool OpenItemWithExternalApp(const string16& full_path) {
  SHELLEXECUTEINFO sei = { sizeof(sei) };
  sei.fMask = SEE_MASK_FLAG_DDEWAIT;
  sei.nShow = SW_SHOWNORMAL;
  sei.lpVerb = L"openas";
  sei.lpFile = full_path.c_str();
  return (TRUE == ::ShellExecuteExW(&sei));
}

bool OpenAnyViaShell(const string16& full_path,
                     const string16& directory,
                     const string16& args,
                     DWORD mask) {
  SHELLEXECUTEINFO sei = { sizeof(sei) };
  sei.fMask = mask;
  sei.nShow = SW_SHOWNORMAL;
  sei.lpFile = full_path.c_str();
  sei.lpDirectory = directory.c_str();
  if (!args.empty())
    sei.lpParameters = args.c_str();

  if (::ShellExecuteExW(&sei))
    return true;
  if (::GetLastError() == ERROR_NO_ASSOCIATION)
    return OpenItemWithExternalApp(full_path);
  return false;
}

bool OpenItemViaShell(const base::FilePath& full_path) {
  return OpenAnyViaShell(full_path.value(), full_path.DirName().value(),
                         string16(), 0);
}

bool OpenItemViaShellNoZoneCheck(const base::FilePath& full_path) {
  return OpenAnyViaShell(full_path.value(), string16(), string16(),
                         SEE_MASK_NOZONECHECKS | SEE_MASK_FLAG_DDEWAIT);
}

void SetAppIdForWindow(const string16& app_id, HWND hwnd) {
  SetAppDetailsForWindow(app_id, string16(), string16(), string16(), hwnd);
}

void SetAppIconForWindow(const string16& app_icon, HWND hwnd) {
  SetAppDetailsForWindow(string16(), app_icon, string16(), string16(), hwnd);
}

void SetRelaunchDetailsForWindow(const string16& relaunch_command,
                                 const string16& display_name,
                                 HWND hwnd) {
  SetAppDetailsForWindow(string16(),
                         string16(),
                         relaunch_command,
                         display_name,
                         hwnd);
}

bool IsAeroGlassEnabled() {
  // For testing in Win8 (where it is not possible to disable composition) the
  // user can specify this command line switch to mimic the behavior.  In this
  // mode, cross-HWND transparency is not supported and various types of
  // widgets fallback to more simplified rendering behavior.
  if (CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kDisableDwmComposition))
    return false;

  if (base::win::GetVersion() < base::win::VERSION_VISTA)
    return false;
  // If composition is not enabled, we behave like on XP.
  BOOL enabled = FALSE;
  return SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled;
}

}  // namespace win
}  // namespace ui