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
137
138
139
140
141
142
|
// 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 "chrome/installer/launcher_support/chrome_launcher_support.h"
#include <windows.h>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/strings/string16.h"
#include "base/win/registry.h"
namespace chrome_launcher_support {
namespace {
// TODO(huangs) Refactor the constants: http://crbug.com/148538
#if defined(GOOGLE_CHROME_BUILD)
const wchar_t kInstallationRegKey[] =
L"Software\\Google\\Update\\ClientState";
// Copied from chrome_appid.cc.
const wchar_t kBinariesAppGuid[] = L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}";
// Copied from google_chrome_distribution.cc.
const wchar_t kBrowserAppGuid[] = L"{8A69D345-D564-463c-AFF1-A69D9E530F96}";
// Copied frome google_chrome_sxs_distribution.cc.
const wchar_t kSxSBrowserAppGuid[] = L"{4ea16ac7-fd5a-47c3-875b-dbf4a2008c20}";
#else
const wchar_t kInstallationRegKey[] = L"Software\\Chromium";
#endif
// Copied from util_constants.cc.
const wchar_t kChromeExe[] = L"chrome.exe";
const wchar_t kUninstallStringField[] = L"UninstallString";
// Reads a string value from the specified product's registry key. Returns true
// iff the value is present and successfully read.
bool GetClientStateValue(InstallationLevel level,
const wchar_t* app_guid,
const wchar_t* value_name,
base::string16* value) {
HKEY root_key = (level == USER_LEVEL_INSTALLATION) ?
HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
base::string16 subkey(kInstallationRegKey);
if (app_guid)
subkey.append(1, L'\\').append(app_guid);
base::win::RegKey reg_key;
// Google Update always uses 32bit hive.
if (reg_key.Open(root_key, subkey.c_str(),
KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
if (reg_key.ReadValue(value_name, value) == ERROR_SUCCESS) {
return true;
}
}
return false;
}
// Reads the path to setup.exe from the value "UninstallString" within the
// specified product's registry key. Returns an empty FilePath if an error
// occurs or the product is not installed at the specified level.
base::FilePath GetSetupExeFromRegistry(InstallationLevel level,
const wchar_t* app_guid) {
base::string16 uninstall;
if (GetClientStateValue(level, app_guid, kUninstallStringField, &uninstall)) {
base::FilePath setup_exe_path(uninstall);
if (base::PathExists(setup_exe_path))
return setup_exe_path;
}
return base::FilePath();
}
// Returns the path to an existing setup.exe at the specified level, if it can
// be found via the registry.
base::FilePath GetSetupExeForInstallationLevel(InstallationLevel level) {
base::FilePath setup_exe_path;
#if defined(GOOGLE_CHROME_BUILD)
// Look in the registry for Chrome Binaries first.
setup_exe_path = GetSetupExeFromRegistry(level, kBinariesAppGuid);
// If the above fails, look in the registry for Chrome next.
if (setup_exe_path.empty())
setup_exe_path = GetSetupExeFromRegistry(level, kBrowserAppGuid);
// If we fail again, then setup_exe_path would be empty.
#else
// For Chromium, there are no GUIDs. Just look in the Chromium registry key.
setup_exe_path = GetSetupExeFromRegistry(level, nullptr);
#endif
return setup_exe_path;
}
// Returns the path to an installed |exe_file| (e.g. chrome.exe) at the
// specified level, given |setup_exe_path| from the registry. Returns empty
// base::FilePath if none found, or if |setup_exe_path| is empty.
base::FilePath FindExeRelativeToSetupExe(const base::FilePath setup_exe_path,
const wchar_t* exe_file) {
if (!setup_exe_path.empty()) {
// The uninstall path contains the path to setup.exe, which is two levels
// down from |exe_file|. Move up two levels (plus one to drop the file
// name) and look for chrome.exe from there.
base::FilePath exe_path(
setup_exe_path.DirName().DirName().DirName().Append(exe_file));
if (base::PathExists(exe_path))
return exe_path;
// By way of mild future proofing, look up one to see if there's a
// |exe_file| in the version directory
exe_path = setup_exe_path.DirName().DirName().Append(exe_file);
if (base::PathExists(exe_path))
return exe_path;
}
return base::FilePath();
}
} // namespace
base::FilePath GetChromePathForInstallationLevel(InstallationLevel level,
bool is_sxs) {
if (is_sxs) {
#if defined(GOOGLE_CHROME_BUILD)
return FindExeRelativeToSetupExe(
GetSetupExeFromRegistry(level, kSxSBrowserAppGuid), kChromeExe);
#else
// There is no SxS build for Chromium.
return base::FilePath();
#endif
} else {
return FindExeRelativeToSetupExe(GetSetupExeForInstallationLevel(level),
kChromeExe);
}
}
base::FilePath GetAnyChromePath(bool is_sxs) {
base::FilePath path;
path = GetChromePathForInstallationLevel(SYSTEM_LEVEL_INSTALLATION, is_sxs);
if (path.empty())
path = GetChromePathForInstallationLevel(USER_LEVEL_INSTALLATION, is_sxs);
return path;
}
} // namespace chrome_launcher_support
|