blob: 7e2e7103ce4f9ae839a5e6805ea17753567c6852 [file] [log] [blame]
[email protected]5a542072014-02-24 02:12:091// 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.
4
5#include "chrome_elf/chrome_elf_util.h"
6
caitkpc393a5b2015-05-14 19:56:337#include <assert.h>
[email protected]5a542072014-02-24 02:12:098#include <windows.h>
9
10#include "base/macros.h"
11#include "base/strings/string16.h"
12
caitkpc393a5b2015-05-14 19:56:3313ProcessType g_process_type = ProcessType::UNINITIALIZED;
14
[email protected]5a542072014-02-24 02:12:0915namespace {
16
17const wchar_t kRegPathClientState[] = L"Software\\Google\\Update\\ClientState";
18const wchar_t kRegPathClientStateMedium[] =
19 L"Software\\Google\\Update\\ClientStateMedium";
20#if defined(GOOGLE_CHROME_BUILD)
21const wchar_t kRegPathChromePolicy[] = L"SOFTWARE\\Policies\\Google\\Chrome";
22#else
23const wchar_t kRegPathChromePolicy[] = L"SOFTWARE\\Policies\\Chromium";
24#endif // defined(GOOGLE_CHROME_BUILD)
25
26const wchar_t kRegValueUsageStats[] = L"usagestats";
27const wchar_t kUninstallArgumentsField[] = L"UninstallArguments";
28const wchar_t kMetricsReportingEnabled[] =L"MetricsReportingEnabled";
29
30const wchar_t kAppGuidCanary[] =
31 L"{4ea16ac7-fd5a-47c3-875b-dbf4a2008c20}";
32const wchar_t kAppGuidGoogleChrome[] =
33 L"{8A69D345-D564-463c-AFF1-A69D9E530F96}";
34const wchar_t kAppGuidGoogleBinaries[] =
35 L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}";
36
37bool 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) {
40 HKEY key = NULL;
41 value_out->clear();
42
43 base::string16 full_key_path(key_path);
44 full_key_path.append(1, L'\\');
45 full_key_path.append(guid);
46
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) !=
50 ERROR_SUCCESS) {
51 return false;
52 }
53
54 const size_t kMaxStringLength = 1024;
55 wchar_t raw_value[kMaxStringLength] = {};
56 DWORD size = sizeof(raw_value);
57 DWORD type = REG_SZ;
58 LONG result = ::RegQueryValueEx(key, value_to_read, 0, &type,
59 reinterpret_cast<LPBYTE>(raw_value), &size);
60
61 if (result == ERROR_SUCCESS) {
62 if (type != REG_SZ || (size & 1) != 0) {
63 result = ERROR_NOT_SUPPORTED;
64 } else if (size == 0) {
65 *raw_value = L'\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';
69 else
70 result = ERROR_MORE_DATA;
71 }
72 }
73
74 if (result == ERROR_SUCCESS)
75 *value_out = raw_value;
76
77 ::RegCloseKey(key);
78
79 return result == ERROR_SUCCESS;
80}
81
82bool ReadKeyValueDW(bool system_install, const wchar_t* key_path,
83 base::string16 guid, const wchar_t* value_to_read,
84 DWORD* value_out) {
85 HKEY key = NULL;
86 *value_out = 0;
87
88 base::string16 full_key_path(key_path);
89 full_key_path.append(1, L'\\');
90 full_key_path.append(guid);
91
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) !=
95 ERROR_SUCCESS) {
96 return false;
97 }
98
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);
103
104 ::RegCloseKey(key);
105
106 return result == ERROR_SUCCESS && size == sizeof(*value_out);
107}
108
109} // namespace
110
111bool IsCanary(const wchar_t* exe_path) {
112 return wcsstr(exe_path, L"Chrome SxS\\Application") != NULL;
113}
114
115bool 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))
120 return true;
121
122 ret = ::GetEnvironmentVariable(L"PROGRAMFILES(X86)", program_dir,
123 arraysize(program_dir));
124 if (ret && ret < MAX_PATH && !wcsncmp(exe_path, program_dir, ret))
125 return true;
126
127 return false;
128}
129
130bool IsMultiInstall(bool is_system_install) {
131 base::string16 args;
132 if (!ReadKeyValueString(is_system_install, kRegPathClientState,
133 kAppGuidGoogleChrome, kUninstallArgumentsField,
134 &args)) {
135 return false;
136 }
137 return args.find(L"--multi-install") != base::string16::npos;
138}
139
140bool AreUsageStatsEnabled(const wchar_t* exe_path) {
141 bool enabled = true;
142 bool controlled_by_policy = ReportingIsEnforcedByPolicy(&enabled);
143
144 if (controlled_by_policy && !enabled)
145 return false;
146
147 bool system_install = IsSystemInstall(exe_path);
148 base::string16 app_guid;
149
150 if (IsCanary(exe_path)) {
151 app_guid = kAppGuidCanary;
152 } else {
153 app_guid = IsMultiInstall(system_install) ? kAppGuidGoogleBinaries :
154 kAppGuidGoogleChrome;
155 }
156
157 DWORD out_value = 0;
158 if (system_install &&
159 ReadKeyValueDW(system_install, kRegPathClientStateMedium, app_guid,
160 kRegValueUsageStats, &out_value)) {
161 return out_value == 1;
162 }
163
164 return ReadKeyValueDW(system_install, kRegPathClientState, app_guid,
165 kRegValueUsageStats, &out_value) && out_value == 1;
166}
167
168bool ReportingIsEnforcedByPolicy(bool* breakpad_enabled) {
169 HKEY key = NULL;
170 DWORD value = 0;
171 BYTE* value_bytes = reinterpret_cast<BYTE*>(&value);
172 DWORD size = sizeof(value);
173 DWORD type = REG_DWORD;
174
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;
180 }
181 ::RegCloseKey(key);
182 return size == sizeof(value);
183 }
184
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;
190 }
191 ::RegCloseKey(key);
192 return size == sizeof(value);
193 }
194
195 return false;
196}
[email protected]0884a312014-03-01 01:23:24197
caitkpc393a5b2015-05-14 19:56:33198void InitializeProcessType() {
199 assert(g_process_type == ProcessType::UNINITIALIZED);
[email protected]0884a312014-03-01 01:23:24200 typedef bool (*IsSandboxedProcessFunc)();
201 IsSandboxedProcessFunc is_sandboxed_process_func =
202 reinterpret_cast<IsSandboxedProcessFunc>(
203 GetProcAddress(GetModuleHandle(NULL), "IsSandboxedProcess"));
caitkpc393a5b2015-05-14 19:56:33204 if (is_sandboxed_process_func && is_sandboxed_process_func()) {
205 g_process_type = ProcessType::NON_BROWSER_PROCESS;
206 return;
207 }
[email protected]0884a312014-03-01 01:23:24208
caitkp88dc4192015-05-12 19:58:56209 // TODO(robertshield): Drop the command line check when we drop support for
210 // enabling chrome_elf in unsandboxed processes.
caitkpc393a5b2015-05-14 19:56:33211 const wchar_t* command_line = GetCommandLine();
212 if (command_line && wcsstr(command_line, L"--type")) {
213 g_process_type = ProcessType::NON_BROWSER_PROCESS;
214 return;
215 }
[email protected]0884a312014-03-01 01:23:24216
caitkpc393a5b2015-05-14 19:56:33217 g_process_type = ProcessType::BROWSER_PROCESS;
218}
219
220bool IsNonBrowserProcess() {
221 assert(g_process_type != ProcessType::UNINITIALIZED);
222 return g_process_type == ProcessType::NON_BROWSER_PROCESS;
[email protected]0884a312014-03-01 01:23:24223}