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.
5 #include "chrome_elf/chrome_elf_util.h"
10 #include "base/macros.h"
11 #include "base/strings/string16.h"
13 ProcessType g_process_type
= ProcessType::UNINITIALIZED
;
17 const wchar_t kRegPathClientState
[] = L
"Software\\Google\\Update\\ClientState";
18 const wchar_t kRegPathClientStateMedium
[] =
19 L
"Software\\Google\\Update\\ClientStateMedium";
20 #if defined(GOOGLE_CHROME_BUILD)
21 const wchar_t kRegPathChromePolicy
[] = L
"SOFTWARE\\Policies\\Google\\Chrome";
23 const wchar_t kRegPathChromePolicy
[] = L
"SOFTWARE\\Policies\\Chromium";
24 #endif // defined(GOOGLE_CHROME_BUILD)
26 const wchar_t kRegValueUsageStats
[] = L
"usagestats";
27 const wchar_t kUninstallArgumentsField
[] = L
"UninstallArguments";
28 const wchar_t kMetricsReportingEnabled
[] =L
"MetricsReportingEnabled";
30 const wchar_t kAppGuidCanary
[] =
31 L
"{4ea16ac7-fd5a-47c3-875b-dbf4a2008c20}";
32 const wchar_t kAppGuidGoogleChrome
[] =
33 L
"{8A69D345-D564-463c-AFF1-A69D9E530F96}";
34 const wchar_t kAppGuidGoogleBinaries
[] =
35 L
"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}";
37 bool ReadKeyValueString(bool system_install
, const wchar_t* key_path
,
38 const wchar_t* guid
, const wchar_t* value_to_read
,
39 base::string16
* value_out
) {
43 base::string16
full_key_path(key_path
);
44 full_key_path
.append(1, L
'\\');
45 full_key_path
.append(guid
);
47 if (::RegOpenKeyEx(system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
,
48 full_key_path
.c_str(), 0,
49 KEY_QUERY_VALUE
| KEY_WOW64_32KEY
, &key
) !=
54 const size_t kMaxStringLength
= 1024;
55 wchar_t raw_value
[kMaxStringLength
] = {};
56 DWORD size
= sizeof(raw_value
);
58 LONG result
= ::RegQueryValueEx(key
, value_to_read
, 0, &type
,
59 reinterpret_cast<LPBYTE
>(raw_value
), &size
);
61 if (result
== ERROR_SUCCESS
) {
62 if (type
!= REG_SZ
|| (size
& 1) != 0) {
63 result
= ERROR_NOT_SUPPORTED
;
64 } else if (size
== 0) {
66 } else if (raw_value
[size
/ sizeof(wchar_t) - 1] != L
'\0') {
67 if ((size
/ sizeof(wchar_t)) < kMaxStringLength
)
68 raw_value
[size
/ sizeof(wchar_t)] = L
'\0';
70 result
= ERROR_MORE_DATA
;
74 if (result
== ERROR_SUCCESS
)
75 *value_out
= raw_value
;
79 return result
== ERROR_SUCCESS
;
82 bool ReadKeyValueDW(bool system_install
, const wchar_t* key_path
,
83 base::string16 guid
, const wchar_t* value_to_read
,
88 base::string16
full_key_path(key_path
);
89 full_key_path
.append(1, L
'\\');
90 full_key_path
.append(guid
);
92 if (::RegOpenKeyEx(system_install
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
,
93 full_key_path
.c_str(), 0,
94 KEY_QUERY_VALUE
| KEY_WOW64_32KEY
, &key
) !=
99 DWORD size
= sizeof(*value_out
);
100 DWORD type
= REG_DWORD
;
101 LONG result
= ::RegQueryValueEx(key
, value_to_read
, 0, &type
,
102 reinterpret_cast<BYTE
*>(value_out
), &size
);
106 return result
== ERROR_SUCCESS
&& size
== sizeof(*value_out
);
111 bool IsCanary(const wchar_t* exe_path
) {
112 return wcsstr(exe_path
, L
"Chrome SxS\\Application") != NULL
;
115 bool IsSystemInstall(const wchar_t* exe_path
) {
116 wchar_t program_dir
[MAX_PATH
] = {};
117 DWORD ret
= ::GetEnvironmentVariable(L
"PROGRAMFILES", program_dir
,
118 arraysize(program_dir
));
119 if (ret
&& ret
< MAX_PATH
&& !wcsncmp(exe_path
, program_dir
, ret
))
122 ret
= ::GetEnvironmentVariable(L
"PROGRAMFILES(X86)", program_dir
,
123 arraysize(program_dir
));
124 if (ret
&& ret
< MAX_PATH
&& !wcsncmp(exe_path
, program_dir
, ret
))
130 bool IsMultiInstall(bool is_system_install
) {
132 if (!ReadKeyValueString(is_system_install
, kRegPathClientState
,
133 kAppGuidGoogleChrome
, kUninstallArgumentsField
,
137 return args
.find(L
"--multi-install") != base::string16::npos
;
140 bool AreUsageStatsEnabled(const wchar_t* exe_path
) {
142 bool controlled_by_policy
= ReportingIsEnforcedByPolicy(&enabled
);
144 if (controlled_by_policy
&& !enabled
)
147 bool system_install
= IsSystemInstall(exe_path
);
148 base::string16 app_guid
;
150 if (IsCanary(exe_path
)) {
151 app_guid
= kAppGuidCanary
;
153 app_guid
= IsMultiInstall(system_install
) ? kAppGuidGoogleBinaries
:
154 kAppGuidGoogleChrome
;
158 if (system_install
&&
159 ReadKeyValueDW(system_install
, kRegPathClientStateMedium
, app_guid
,
160 kRegValueUsageStats
, &out_value
)) {
161 return out_value
== 1;
164 return ReadKeyValueDW(system_install
, kRegPathClientState
, app_guid
,
165 kRegValueUsageStats
, &out_value
) && out_value
== 1;
168 bool ReportingIsEnforcedByPolicy(bool* breakpad_enabled
) {
171 BYTE
* value_bytes
= reinterpret_cast<BYTE
*>(&value
);
172 DWORD size
= sizeof(value
);
173 DWORD type
= REG_DWORD
;
175 if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE
, kRegPathChromePolicy
, 0,
176 KEY_QUERY_VALUE
, &key
) == ERROR_SUCCESS
) {
177 if (::RegQueryValueEx(key
, kMetricsReportingEnabled
, 0, &type
,
178 value_bytes
, &size
) == ERROR_SUCCESS
) {
179 *breakpad_enabled
= value
!= 0;
182 return size
== sizeof(value
);
185 if (::RegOpenKeyEx(HKEY_CURRENT_USER
, kRegPathChromePolicy
, 0,
186 KEY_QUERY_VALUE
, &key
) == ERROR_SUCCESS
) {
187 if (::RegQueryValueEx(key
, kMetricsReportingEnabled
, 0, &type
,
188 value_bytes
, &size
) == ERROR_SUCCESS
) {
189 *breakpad_enabled
= value
!= 0;
192 return size
== sizeof(value
);
198 void InitializeProcessType() {
199 assert(g_process_type
== ProcessType::UNINITIALIZED
);
200 typedef bool (*IsSandboxedProcessFunc
)();
201 IsSandboxedProcessFunc is_sandboxed_process_func
=
202 reinterpret_cast<IsSandboxedProcessFunc
>(
203 GetProcAddress(GetModuleHandle(NULL
), "IsSandboxedProcess"));
204 if (is_sandboxed_process_func
&& is_sandboxed_process_func()) {
205 g_process_type
= ProcessType::NON_BROWSER_PROCESS
;
209 // TODO(robertshield): Drop the command line check when we drop support for
210 // enabling chrome_elf in unsandboxed processes.
211 const wchar_t* command_line
= GetCommandLine();
212 if (command_line
&& wcsstr(command_line
, L
"--type")) {
213 g_process_type
= ProcessType::NON_BROWSER_PROCESS
;
217 g_process_type
= ProcessType::BROWSER_PROCESS
;
220 bool IsNonBrowserProcess() {
221 assert(g_process_type
!= ProcessType::UNINITIALIZED
);
222 return g_process_type
== ProcessType::NON_BROWSER_PROCESS
;