Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(195)

Side by Side Diff: chrome/install_static/install_util.cc

Issue 1913943003: Remove dependencies on chrome\installer from the ChromeCrashReporterClient class on Windows. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix build error Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/install_static/install_util.h" 5 #include "chrome/install_static/install_util.h"
6 6
7 #include <windows.h>
7 #include <assert.h> 8 #include <assert.h>
8 #include <windows.h> 9 #include <memory>
9 #include <stddef.h>
10 10
11 #include "base/macros.h" 11 #include "base/macros.h"
12 #include "base/strings/string16.h" 12 #include "build/build_config.h"
13
14 namespace install_static {
13 15
14 ProcessType g_process_type = ProcessType::UNINITIALIZED; 16 ProcessType g_process_type = ProcessType::UNINITIALIZED;
15 17
16 namespace { 18 // TODO(ananta)
19 // http://crbug.com/604923
20 // The constants defined in this file are also defined in chrome/installer and
21 // other places. we need to unify them.
17 22
23 // Chrome channel display names.
24 const wchar_t kChromeChannelUnknown[] = L"unknown";
25 const wchar_t kChromeChannelCanary[] = L"canary";
26 const wchar_t kChromeChannelDev[] = L"dev";
27 const wchar_t kChromeChannelBeta[] = L"beta";
28 const wchar_t kChromeChannelStable[] = L"";
29 const wchar_t kChromeChannelStableExplicit[] = L"stable";
30
31
32 #if defined(GOOGLE_CHROME_BUILD)
18 const wchar_t kRegPathClientState[] = L"Software\\Google\\Update\\ClientState"; 33 const wchar_t kRegPathClientState[] = L"Software\\Google\\Update\\ClientState";
19 const wchar_t kRegPathClientStateMedium[] = 34 const wchar_t kRegPathClientStateMedium[] =
20 L"Software\\Google\\Update\\ClientStateMedium"; 35 L"Software\\Google\\Update\\ClientStateMedium";
21 #if defined(GOOGLE_CHROME_BUILD)
22 const wchar_t kRegPathChromePolicy[] = L"SOFTWARE\\Policies\\Google\\Chrome"; 36 const wchar_t kRegPathChromePolicy[] = L"SOFTWARE\\Policies\\Google\\Chrome";
37 const wchar_t kRegApField[] = L"ap";
23 #else 38 #else
39 const wchar_t kRegPathClientState[] =
40 L"Software\\Chromium\\Update\\ClientState";
41 const wchar_t kRegPathClientStateMedium[] =
42 L"Software\\Chromium\\Update\\ClientStateMedium";
24 const wchar_t kRegPathChromePolicy[] = L"SOFTWARE\\Policies\\Chromium"; 43 const wchar_t kRegPathChromePolicy[] = L"SOFTWARE\\Policies\\Chromium";
25 #endif // defined(GOOGLE_CHROME_BUILD) 44 #endif
26 45
27 const wchar_t kRegValueUsageStats[] = L"usagestats"; 46 const wchar_t kRegValueUsageStats[] = L"usagestats";
28 const wchar_t kUninstallArgumentsField[] = L"UninstallArguments"; 47 const wchar_t kUninstallArgumentsField[] = L"UninstallArguments";
29 const wchar_t kMetricsReportingEnabled[] = L"MetricsReportingEnabled"; 48 const wchar_t kMetricsReportingEnabled[] = L"MetricsReportingEnabled";
30 49
31 const wchar_t kAppGuidCanary[] = 50 const wchar_t kAppGuidCanary[] =
32 L"{4ea16ac7-fd5a-47c3-875b-dbf4a2008c20}"; 51 L"{4ea16ac7-fd5a-47c3-875b-dbf4a2008c20}";
33 const wchar_t kAppGuidGoogleChrome[] = 52 const wchar_t kAppGuidGoogleChrome[] =
34 L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; 53 L"{8A69D345-D564-463c-AFF1-A69D9E530F96}";
35 const wchar_t kAppGuidGoogleBinaries[] = 54 const wchar_t kAppGuidGoogleBinaries[] =
36 L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}"; 55 L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}";
37 56
57 namespace {
58
59 // TODO(ananta)
60 // http://crbug.com/604923
61 // These constants are defined in the chrome/installer directory as well. We
62 // need to unify them.
63 #if defined(GOOGLE_CHROME_BUILD)
64 const wchar_t kSxSSuffix[] = L" SxS";
65 const wchar_t kGoogleChromeInstallSubDir1[] = L"Google";
66 const wchar_t kGoogleChromeInstallSubDir2[] = L"Chrome";
67 #else
68 const wchar_t kChromiumInstallSubDir[] = L"Chromium";
69 #endif // defined(GOOGLE_CHROME_BUILD)
70
71 const wchar_t kUserDataDirname[] = L"User Data";
72 const wchar_t kBrowserCrashDumpMetricsSubKey[] = L"\\BrowserCrashDumpAttempts";
73
74 const wchar_t kRegPathGoogleUpdate[] = L"Software\\Google\\Update";
75 const wchar_t kRegGoogleUpdateVersion[] = L"version";
76
77 void Trace(const wchar_t* format_string, ...) {
78 static const int kMaxLogBufferSize = 1024;
79 static wchar_t buffer[kMaxLogBufferSize] = {};
80
81 va_list args = {};
82
83 va_start(args, format_string);
84 vswprintf(buffer, arraysize(buffer), format_string, args);
85 OutputDebugString(buffer);
86 va_end(args);
87 }
88
89 // Reads a string value identified by |value_to_read| from the registry path
90 // under |key_path|. We look in HKLM or HKCU depending on whether the
91 // |system_install| parameter is true.
92 // Please note that this function only looks in the 32bit view of the registry.
38 bool ReadKeyValueString(bool system_install, const wchar_t* key_path, 93 bool ReadKeyValueString(bool system_install, const wchar_t* key_path,
39 const wchar_t* guid, const wchar_t* value_to_read, 94 const wchar_t* guid, const wchar_t* value_to_read,
40 base::string16* value_out) { 95 base::string16* value_out) {
41 HKEY key = NULL; 96 HKEY key = NULL;
42 value_out->clear(); 97 value_out->clear();
43 98
44 base::string16 full_key_path(key_path); 99 base::string16 full_key_path(key_path);
45 full_key_path.append(1, L'\\'); 100 if (guid && *guid) {
46 full_key_path.append(guid); 101 full_key_path.append(1, L'\\');
102 full_key_path.append(guid);
103 }
47 104
48 if (::RegOpenKeyEx(system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, 105 if (::RegOpenKeyEx(system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
49 full_key_path.c_str(), 0, 106 full_key_path.c_str(), 0,
50 KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key) != 107 KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key) !=
51 ERROR_SUCCESS) { 108 ERROR_SUCCESS) {
52 return false; 109 return false;
53 } 110 }
54 111
55 const size_t kMaxStringLength = 1024; 112 const size_t kMaxStringLength = 1024;
56 wchar_t raw_value[kMaxStringLength] = {}; 113 wchar_t raw_value[kMaxStringLength] = {};
(...skipping 16 matching lines...) Expand all
73 } 130 }
74 131
75 if (result == ERROR_SUCCESS) 132 if (result == ERROR_SUCCESS)
76 *value_out = raw_value; 133 *value_out = raw_value;
77 134
78 ::RegCloseKey(key); 135 ::RegCloseKey(key);
79 136
80 return result == ERROR_SUCCESS; 137 return result == ERROR_SUCCESS;
81 } 138 }
82 139
140 // Reads a DWORD value identified by |value_to_read| from the registry path
141 // under |key_path|. We look in HKLM or HKCU depending on whether the
142 // |system_install| parameter is true.
143 // Please note that this function only looks in the 32bit view of the registry.
83 bool ReadKeyValueDW(bool system_install, const wchar_t* key_path, 144 bool ReadKeyValueDW(bool system_install, const wchar_t* key_path,
84 base::string16 guid, const wchar_t* value_to_read, 145 base::string16 guid, const wchar_t* value_to_read,
85 DWORD* value_out) { 146 DWORD* value_out) {
86 HKEY key = NULL; 147 HKEY key = NULL;
87 *value_out = 0; 148 *value_out = 0;
88 149
89 base::string16 full_key_path(key_path); 150 base::string16 full_key_path(key_path);
90 full_key_path.append(1, L'\\'); 151 full_key_path.append(1, L'\\');
91 full_key_path.append(guid); 152 full_key_path.append(guid);
92 153
93 if (::RegOpenKeyEx(system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, 154 if (::RegOpenKeyEx(system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
94 full_key_path.c_str(), 0, 155 full_key_path.c_str(), 0,
95 KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key) != 156 KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key) !=
96 ERROR_SUCCESS) { 157 ERROR_SUCCESS) {
97 return false; 158 return false;
98 } 159 }
99 160
100 DWORD size = sizeof(*value_out); 161 DWORD size = sizeof(*value_out);
101 DWORD type = REG_DWORD; 162 DWORD type = REG_DWORD;
102 LONG result = ::RegQueryValueEx(key, value_to_read, 0, &type, 163 LONG result = ::RegQueryValueEx(key, value_to_read, 0, &type,
103 reinterpret_cast<BYTE*>(value_out), &size); 164 reinterpret_cast<BYTE*>(value_out), &size);
104 165
105 ::RegCloseKey(key); 166 ::RegCloseKey(key);
106 167
107 return result == ERROR_SUCCESS && size == sizeof(*value_out); 168 return result == ERROR_SUCCESS && size == sizeof(*value_out);
108 } 169 }
109 170
171 bool GetLanguageAndCodePageFromVersionResource(const char* version_resource,
172 WORD* language,
173 WORD* code_page) {
174 if (!version_resource)
175 return false;
176
177 struct LanguageAndCodePage {
178 WORD language;
179 WORD code_page;
180 };
181
182 LanguageAndCodePage* translation_info = nullptr;
183 uint32_t data_size_in_bytes = 0;
184 BOOL query_result = VerQueryValue(version_resource,
185 L"\\VarFileInfo\\Translation",
186 reinterpret_cast<void**>(&translation_info),
187 &data_size_in_bytes);
188 if (!query_result)
189 return false;
190
191 *language = translation_info->language;
192 *code_page = translation_info->code_page;
193 return true;
194 }
195
196 bool GetValueFromVersionResource(const char* version_resource,
197 const base::string16& name,
198 base::string16* value_str) {
199 assert(value_str);
200 value_str->clear();
201
202 // TODO(ananta)
203 // It may be better in the long run to enumerate the languages and code pages
204 // in the version resource and return the value from the first match.
205 WORD language = 0;
206 WORD code_page = 0;
207 if (!GetLanguageAndCodePageFromVersionResource(version_resource,
208 &language,
209 &code_page)) {
210 return false;
211 }
212
213 WORD lang_codepage[8] = {};
214 size_t i = 0;
215 // Use the language and codepage
216 lang_codepage[i++] = language;
217 lang_codepage[i++] = code_page;
218 // Use the default language and codepage from the resource.
219 lang_codepage[i++] = ::GetUserDefaultLangID();
220 lang_codepage[i++] = code_page;
221 // Use the language from the resource and Latin codepage (most common).
222 lang_codepage[i++] = language;
223 lang_codepage[i++] = 1252;
224 // Use the default language and Latin codepage (most common).
225 lang_codepage[i++] = ::GetUserDefaultLangID();
226 lang_codepage[i++] = 1252;
227
228 static_assert((arraysize(lang_codepage) % 2) == 0,
229 "Language code page size should be a multiple of 2");
230 assert(arraysize(lang_codepage) == i);
231
232 for (i = 0; i < arraysize(lang_codepage);) {
233 wchar_t sub_block[MAX_PATH];
234 WORD language = lang_codepage[i++];
235 WORD code_page = lang_codepage[i++];
236 _snwprintf_s(sub_block, MAX_PATH, MAX_PATH,
237 L"\\StringFileInfo\\%04hx%04hx\\%ls", language, code_page,
238 name.c_str());
239 void* value = nullptr;
240 uint32_t size = 0;
241 BOOL r = ::VerQueryValue(version_resource, sub_block, &value, &size);
242 if (r && value) {
243 value_str->assign(static_cast<wchar_t*>(value));
244 return true;
245 }
246 }
247 return false;
248 }
249
250 // Returns the executable path for the current process.
251 base::string16 GetCurrentProcessExePath() {
252 wchar_t exe_path[MAX_PATH];
253 if (GetModuleFileName(nullptr, exe_path, arraysize(exe_path)) == 0)
254 return base::string16();
255 return exe_path;
256 }
257
258 // UTF8 to UTF16 and vice versa conversion helpers. We cannot use the base
259 // string conversion utilities here as they bring about a dependency on
260 // user32.dll which is not allowed in this file.
261
262 // Convert a UTF16 string to an UTF8 string.
263 std::string utf16_to_utf8(const base::string16 &source) {
264 if (source.empty())
265 return std::string();
266 int size = ::WideCharToMultiByte(CP_UTF8, 0, &source[0],
267 static_cast<int>(source.size()), nullptr, 0, nullptr, nullptr);
268 std::string result(size, '\0');
269 if (::WideCharToMultiByte(CP_UTF8, 0, &source[0],
270 static_cast<int>(source.size()), &result[0], size, nullptr,
271 nullptr) != size) {
272 assert(false);
273 return std::string();
274 }
275 return result;
276 }
277
278 // Convert a UTF8 string to a UTF16 string.
279 base::string16 utf8_to_string16(const std::string &source) {
280 if (source.empty())
281 return base::string16();
282 int size = ::MultiByteToWideChar(CP_UTF8, 0, &source[0],
283 static_cast<int>(source.size()), nullptr, 0);
284 base::string16 result(size, L'\0');
285 if (::MultiByteToWideChar(CP_UTF8, 0, &source[0],
286 static_cast<int>(source.size()), &result[0], size) != size) {
287 assert(false);
288 return base::string16();
289 }
290 return result;
291 }
292
293 bool RecursiveDirectoryCreate(const base::string16& full_path) {
294 // If the path exists, we've succeeded if it's a directory, failed otherwise.
295 const wchar_t* full_path_str = full_path.c_str();
296 DWORD file_attributes = ::GetFileAttributes(full_path_str);
297 if (file_attributes != INVALID_FILE_ATTRIBUTES) {
298 if ((file_attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
299 Trace(L"%hs( %ls directory exists )\n", __FUNCTION__, full_path_str);
300 return true;
301 }
302 Trace(L"%hs( %ls directory conflicts with an existing file. )\n",
303 __FUNCTION__, full_path_str);
304 return false;
305 }
306
307 // Invariant: Path does not exist as file or directory.
308
309 // Attempt to create the parent recursively. This will immediately return
310 // true if it already exists, otherwise will create all required parent
311 // directories starting with the highest-level missing parent.
312 base::string16 parent_path;
313 std::size_t pos = full_path.find_last_of(L"/\\");
314 if (pos != base::string16::npos) {
315 parent_path = full_path.substr(0, pos);
316 if (!RecursiveDirectoryCreate(parent_path)) {
317 Trace(L"Failed to create one of the parent directories");
318 return false;
319 }
320 }
321 if (!::CreateDirectory(full_path_str, NULL)) {
322 DWORD error_code = ::GetLastError();
323 if (error_code == ERROR_ALREADY_EXISTS) {
324 DWORD file_attributes = GetFileAttributes(full_path_str);
grt (UTC plus 2) 2016/05/03 10:47:55 nit: ::GetFileAttributes as above
ananta 2016/05/03 21:40:57 Done.
325 if ((file_attributes != INVALID_FILE_ATTRIBUTES) &&
326 ((file_attributes & FILE_ATTRIBUTE_DIRECTORY) != 0)) {
327 // This error code ERROR_ALREADY_EXISTS doesn't indicate whether we
328 // were racing with someone creating the same directory, or a file
329 // with the same path. If the directory exists, we lost the
330 // race to create the same directory.
331 return true;
332 } else {
333 Trace(L"Failed to create directory %ls, last error is %d\n",
334 full_path_str, error_code);
335 return false;
336 }
337 }
338 }
339 return true;
340 }
341
342 bool GetCollectStatsConsentImpl(const base::string16& exe_path) {
343 bool enabled = true;
344 if (ReportingIsEnforcedByPolicy(&enabled))
345 return enabled;
346
347 bool system_install = IsSystemInstall(exe_path.c_str());
348 base::string16 app_guid;
349
350 if (IsSxSChrome(exe_path.c_str())) {
351 app_guid = kAppGuidCanary;
352 } else {
353 app_guid = IsMultiInstall(system_install) ? kAppGuidGoogleBinaries :
354 kAppGuidGoogleChrome;
355 }
356
357 DWORD out_value = 0;
358 if (system_install &&
359 ReadKeyValueDW(system_install, kRegPathClientStateMedium, app_guid,
360 kRegValueUsageStats, &out_value)) {
361 return out_value == 1;
362 }
363
364 return ReadKeyValueDW(system_install, kRegPathClientState, app_guid,
365 kRegValueUsageStats, &out_value) && out_value == 1;
366 }
367
368 // Returns true if the |source| string matches the |pattern|. The pattern
369 // may contain wildcards like '?' which matches one character or a '*'
370 // which matches 0 or more characters.
371 // Please note that pattern matches the whole string. If you want to find
372 // something in the middle of the string then you need to specify the pattern
373 // as '*xyz*'.
374 // |source_index| is the index of the current character being matched in
375 // |source|.
376 // |pattern_index| is the index of the current pattern character in |pattern|
377 // which is matched with source.
378 bool MatchPatternImpl(const base::string16& source,
379 const base::string16& pattern,
380 size_t source_index,
381 size_t pattern_index) {
382 if (source.empty() && pattern.empty())
383 return true;
384
385 if (source_index > source.length() || pattern_index > pattern.length())
386 return false;
387
388 // If we reached the end of both strings, then we are done.
389 if ((source_index == source.length()) &&
390 (pattern_index == pattern.length())) {
391 return true;
392 }
393
394 // If the current character in the pattern is a '*' then make sure that
395 // characters after the pattern are present in the source string. This
396 // assumes that you won't have two consecutive '*' characters in the pattern.
397 if ((pattern[pattern_index] == L'*') &&
398 (pattern_index + 1 < pattern.length()) &&
399 (source_index >= source.length())) {
400 return false;
401 }
402
403 // If the pattern contains wildcard characters '?' or '.' or there is a match
404 // then move ahead in both strings.
405 if ((pattern[pattern_index] == L'?') ||
406 (pattern[pattern_index] == source[source_index])) {
407 return MatchPatternImpl(source, pattern, source_index + 1,
408 pattern_index + 1);
409 }
410
411 // If we have a '*' then there are two possibilities
412 // 1. We consider current character of source.
413 // 2. We ignore current character of source.
414 if (pattern[pattern_index] == L'*') {
415 return MatchPatternImpl(source, pattern, source_index + 1,
416 pattern_index) ||
417 MatchPatternImpl(source, pattern, source_index, pattern_index + 1);
418 }
419 return false;
420 }
421
110 } // namespace 422 } // namespace
111 423
112 bool IsCanary(const wchar_t* exe_path) { 424 bool IsSxSChrome(const wchar_t* exe_path) {
113 return wcsstr(exe_path, L"Chrome SxS\\Application") != NULL; 425 return wcsstr(exe_path, L"Chrome SxS\\Application") != NULL;
114 } 426 }
115 427
116 bool IsSystemInstall(const wchar_t* exe_path) { 428 bool IsSystemInstall(const wchar_t* exe_path) {
117 wchar_t program_dir[MAX_PATH] = {}; 429 wchar_t program_dir[MAX_PATH] = {};
118 DWORD ret = ::GetEnvironmentVariable(L"PROGRAMFILES", program_dir, 430 DWORD ret = ::GetEnvironmentVariable(L"PROGRAMFILES", program_dir,
119 arraysize(program_dir)); 431 arraysize(program_dir));
120 if (ret && ret < MAX_PATH && !wcsncmp(exe_path, program_dir, ret)) 432 if (ret && ret < arraysize(program_dir) &&
433 !wcsnicmp(exe_path, program_dir, ret)) {
121 return true; 434 return true;
435 }
122 436
123 ret = ::GetEnvironmentVariable(L"PROGRAMFILES(X86)", program_dir, 437 ret = ::GetEnvironmentVariable(L"PROGRAMFILES(X86)", program_dir,
124 arraysize(program_dir)); 438 arraysize(program_dir));
125 if (ret && ret < MAX_PATH && !wcsncmp(exe_path, program_dir, ret)) 439 if (ret && ret < arraysize(program_dir) &&
440 !wcsnicmp(exe_path, program_dir, ret)) {
126 return true; 441 return true;
442 }
127 443
128 return false; 444 return false;
129 } 445 }
130 446
131 bool IsMultiInstall(bool is_system_install) { 447 bool IsMultiInstall(bool is_system_install) {
132 base::string16 args; 448 base::string16 args;
133 if (!ReadKeyValueString(is_system_install, kRegPathClientState, 449 if (!ReadKeyValueString(is_system_install, kRegPathClientState,
134 kAppGuidGoogleChrome, kUninstallArgumentsField, 450 kAppGuidGoogleChrome, kUninstallArgumentsField,
135 &args)) { 451 &args)) {
136 return false; 452 return false;
137 } 453 }
138 return args.find(L"--multi-install") != base::string16::npos; 454 return args.find(L"--multi-install") != base::string16::npos;
139 } 455 }
140 456
141 bool AreUsageStatsEnabled(const wchar_t* exe_path) { 457 bool GetCollectStatsConsent() {
142 bool enabled = true; 458 return GetCollectStatsConsentImpl(GetCurrentProcessExePath());
143 bool controlled_by_policy = ReportingIsEnforcedByPolicy(&enabled);
144
145 if (controlled_by_policy && !enabled)
146 return false;
147
148 bool system_install = IsSystemInstall(exe_path);
149 base::string16 app_guid;
150
151 if (IsCanary(exe_path)) {
152 app_guid = kAppGuidCanary;
153 } else {
154 app_guid = IsMultiInstall(system_install) ? kAppGuidGoogleBinaries :
155 kAppGuidGoogleChrome;
156 }
157
158 DWORD out_value = 0;
159 if (system_install &&
160 ReadKeyValueDW(system_install, kRegPathClientStateMedium, app_guid,
161 kRegValueUsageStats, &out_value)) {
162 return out_value == 1;
163 }
164
165 return ReadKeyValueDW(system_install, kRegPathClientState, app_guid,
166 kRegValueUsageStats, &out_value) && out_value == 1;
167 } 459 }
168 460
169 bool ReportingIsEnforcedByPolicy(bool* breakpad_enabled) { 461 bool GetCollectStatsConsentForTesting(const base::string16& exe_path) {
462 return GetCollectStatsConsentImpl(exe_path);
463 }
464
465 bool ReportingIsEnforcedByPolicy(bool* metrics_is_enforced_by_policy) {
170 HKEY key = NULL; 466 HKEY key = NULL;
171 DWORD value = 0; 467 DWORD value = 0;
172 BYTE* value_bytes = reinterpret_cast<BYTE*>(&value); 468 BYTE* value_bytes = reinterpret_cast<BYTE*>(&value);
173 DWORD size = sizeof(value); 469 DWORD size = sizeof(value);
174 DWORD type = REG_DWORD; 470 DWORD type = REG_DWORD;
175 471
176 if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, kRegPathChromePolicy, 0, 472 if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, kRegPathChromePolicy, 0,
177 KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) { 473 KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) {
178 if (::RegQueryValueEx(key, kMetricsReportingEnabled, 0, &type, 474 if (::RegQueryValueEx(key, kMetricsReportingEnabled, 0, &type,
179 value_bytes, &size) == ERROR_SUCCESS) { 475 value_bytes, &size) == ERROR_SUCCESS) {
180 *breakpad_enabled = value != 0; 476 *metrics_is_enforced_by_policy = value != 0;
181 } 477 }
182 ::RegCloseKey(key); 478 ::RegCloseKey(key);
183 return size == sizeof(value); 479 return size == sizeof(value);
184 } 480 }
185 481
186 if (::RegOpenKeyEx(HKEY_CURRENT_USER, kRegPathChromePolicy, 0, 482 if (::RegOpenKeyEx(HKEY_CURRENT_USER, kRegPathChromePolicy, 0,
187 KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) { 483 KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) {
188 if (::RegQueryValueEx(key, kMetricsReportingEnabled, 0, &type, 484 if (::RegQueryValueEx(key, kMetricsReportingEnabled, 0, &type,
189 value_bytes, &size) == ERROR_SUCCESS) { 485 value_bytes, &size) == ERROR_SUCCESS) {
190 *breakpad_enabled = value != 0; 486 *metrics_is_enforced_by_policy = value != 0;
191 } 487 }
192 ::RegCloseKey(key); 488 ::RegCloseKey(key);
193 return size == sizeof(value); 489 return size == sizeof(value);
194 } 490 }
195 491
196 return false; 492 return false;
197 } 493 }
198 494
199 void InitializeProcessType() { 495 void InitializeProcessType() {
200 assert(g_process_type == ProcessType::UNINITIALIZED); 496 assert(g_process_type == ProcessType::UNINITIALIZED);
(...skipping 14 matching lines...) Expand all
215 return; 511 return;
216 } 512 }
217 513
218 g_process_type = ProcessType::BROWSER_PROCESS; 514 g_process_type = ProcessType::BROWSER_PROCESS;
219 } 515 }
220 516
221 bool IsNonBrowserProcess() { 517 bool IsNonBrowserProcess() {
222 assert(g_process_type != ProcessType::UNINITIALIZED); 518 assert(g_process_type != ProcessType::UNINITIALIZED);
223 return g_process_type == ProcessType::NON_BROWSER_PROCESS; 519 return g_process_type == ProcessType::NON_BROWSER_PROCESS;
224 } 520 }
521
522 bool GetDefaultUserDataDirectory(base::string16* result) {
523 static const wchar_t kLocalAppData[] = L"%LOCALAPPDATA%";
524
525 std::unique_ptr<wchar_t> user_data_dir_path;
526
527 // This environment variable should be set on Windows 7 and up.
528 // If we fail to find this variable then we default to the temporary files
529 // path.
530 DWORD size = ::ExpandEnvironmentStrings(kLocalAppData, nullptr, 0);
531 if (size) {
532 user_data_dir_path.reset(new wchar_t[size]);
533 if (::ExpandEnvironmentStrings(kLocalAppData,
534 user_data_dir_path.get(),
535 size) != size) {
536 user_data_dir_path.reset();
537 }
538 }
539 // We failed to find the %LOCALAPPDATA% folder. Fallback to the temporary
540 // files path. If we fail to find this we bail.
541 if (!user_data_dir_path.get()) {
542 size = ::GetTempPath(0, nullptr);
543 if (!size)
544 return false;
545 user_data_dir_path.reset(new wchar_t[size + 1]);
546 if (::GetTempPath(size + 1, user_data_dir_path.get()) != size)
547 return false;
548 }
549
550 base::string16 install_sub_directory = GetChromeInstallSubDirectory();
551
552 *result = user_data_dir_path.get();
553 if ((*result)[result->length() - 1] != L'\\')
554 result->append(L"\\");
555 result->append(install_sub_directory);
556 result->append(L"\\");
557 result->append(kUserDataDirname);
558 return true;
559 }
560
561 bool GetDefaultCrashDumpLocation(base::string16* crash_dir) {
562 // In order to be able to start crash handling very early, we do not rely on
563 // chrome's PathService entries (for DIR_CRASH_DUMPS) being available on
564 // Windows. See https://crbug.com/564398.
565 if (!GetDefaultUserDataDirectory(crash_dir))
566 return false;
567
568 // We have to make sure the user data dir exists on first run. See
569 // http://crbug.com/591504.
570 if (!RecursiveDirectoryCreate(crash_dir->c_str()))
571 return false;
572 crash_dir->append(L"\\Crashpad");
573 return true;
574 }
575
576
577 std::string GetEnvironmentString(const std::string& variable_name) {
578 DWORD value_length = ::GetEnvironmentVariable(
579 utf8_to_string16(variable_name).c_str(), NULL, 0);
580 if (value_length == 0)
581 return std::string();
582 std::unique_ptr<wchar_t[]> value(new wchar_t[value_length]);
583 ::GetEnvironmentVariable(utf8_to_string16(variable_name).c_str(),
584 value.get(), value_length);
585 return utf16_to_utf8(value.get());
586 }
587
588 bool SetEnvironmentString(const std::string& variable_name,
589 const std::string& new_value) {
590 return !!SetEnvironmentVariable(utf8_to_string16(variable_name).c_str(),
591 utf8_to_string16(new_value).c_str());
592 }
593
594 bool HasEnvironmentVariable(const std::string& variable_name) {
595 return !!::GetEnvironmentVariable(utf8_to_string16(variable_name).c_str(),
596 NULL, 0);
597 }
598
599 bool GetExecutableVersionDetails(const base::string16& exe_path,
600 base::string16* product_name,
601 base::string16* version,
602 base::string16* special_build,
603 base::string16* channel_name) {
604 assert(product_name);
605 assert(version);
606 assert(special_build);
607 assert(channel_name);
608
609 // Default values in case we don't find a version resource.
610 *product_name = L"Chrome";
611 *version = L"0.0.0.0-devel";
612 *channel_name = kChromeChannelUnknown;
613 special_build->clear();
614
615 DWORD dummy = 0;
616 DWORD length = ::GetFileVersionInfoSize(exe_path.c_str(), &dummy);
617 if (length) {
618 std::unique_ptr<char> data(new char[length]);
619 if (::GetFileVersionInfo(exe_path.c_str(), dummy, length,
620 data.get())) {
621 GetValueFromVersionResource(data.get(), L"ProductVersion", version);
622
623 base::string16 official_build;
624 GetValueFromVersionResource(data.get(), L"Official Build",
625 &official_build);
626 if (official_build != L"1")
627 version->append(L"-devel");
628 GetValueFromVersionResource(data.get(), L"ProductShortName",
629 product_name);
630 GetValueFromVersionResource(data.get(), L"SpecialBuild", special_build);
631 }
632 }
633 GetChromeChannelName(!IsSystemInstall(exe_path.c_str()), channel_name);
634 return true;
635 }
636
637 void GetChromeChannelName(bool is_per_user_install,
grt (UTC plus 2) 2016/05/03 10:47:55 please add a unit test for this that at least cove
grt (UTC plus 2) 2016/05/03 15:54:55 FWIW, adding a new test binary is much easier than
ananta 2016/05/03 21:40:57 Added a unittest in chrome_elf_unittests for now.
638 base::string16* channel_name) {
639 #if !defined(GOOGLE_CHROME_BUILD)
640 *channel_name = kChromeChannelUnknown;
641 return;
642 #else
643 channel_name->clear();
644 // TODO(ananta)
645 // http://crbug.com/604923
646 // Unify this with the chrome/installer/util/channel_info.h/.cc.
647 if (IsSxSChrome(GetCurrentProcessExePath().c_str())) {
648 *channel_name = L"canary";
649 } else {
650 base::string16 value;
651 if (ReadKeyValueString(!is_per_user_install,
652 kRegPathClientState,
653 kAppGuidGoogleChrome,
grt (UTC plus 2) 2016/05/03 15:54:55 if kAppGuidGoogleChrome indicates that this is mul
ananta 2016/05/03 21:40:57 Done.
654 kRegApField,
655 &value)) {
656 static const wchar_t kChromeChannelBetaPattern[] = L"1?1-";
grt (UTC plus 2) 2016/05/03 10:47:55 * at end of this pattern
ananta 2016/05/03 21:40:56 Done.
657 static const wchar_t kChromeChannelBetaX64Pattern[] = L"*x64-beta*";
658 static const wchar_t kChromeChannelDevPattern[] = L"2?0-d";
grt (UTC plus 2) 2016/05/03 10:47:55 * at end of this pattern
ananta 2016/05/03 21:40:56 Done.
659 static const wchar_t kChromeChannelDevX64Pattern[] = L"x64-dev";
grt (UTC plus 2) 2016/05/03 10:47:55 * on both ends of this pattern
ananta 2016/05/03 21:40:56 Done.
660 static const wchar_t kChromeStableMultiInstallPattern[] = L"*multi*";
grt (UTC plus 2) 2016/05/03 10:47:55 *-multi*
ananta 2016/05/03 21:40:57 Done.
661
662 std::transform(value.begin(), value.end(), value.begin(), ::tolower);
663
664 // Channel names containing stable should be reported as an empty string.
665 if (value.find(kChromeChannelStableExplicit) !=
grt (UTC plus 2) 2016/05/03 15:54:55 // Empty channel names and those containing "stabl
ananta 2016/05/03 21:40:57 Done.
666 base::string16::npos) {
667 return;
668 }
669
670 if (MatchPattern(value, kChromeChannelDevPattern) ||
671 MatchPattern(value, kChromeChannelDevX64Pattern)) {
672 channel_name->assign(kChromeChannelDev);
673 }
674
675 if (MatchPattern(value, kChromeChannelBetaPattern) ||
676 MatchPattern(value, kChromeChannelBetaPattern)) {
grt (UTC plus 2) 2016/05/03 10:47:55 BetaX64
ananta 2016/05/03 21:40:57 Done.
677 channel_name->assign(kChromeChannelBeta);
678 }
679
680 if (value.find(kChromeStableMultiInstallPattern) !=
681 base::string16::npos) {
682 *channel_name = L"-m";
grt (UTC plus 2) 2016/05/03 10:47:55 append
grt (UTC plus 2) 2016/05/03 15:54:55 on second thought, you need to add support for cal
ananta 2016/05/03 21:40:57 Done.
683 }
684
685 // If we fail to find any matching pattern in the channel name then we
686 // default to empty which means stable. Not sure if this is ok.
687 // TODO(ananta)
688 // http://crbug.com/604923
689 // Check if this is ok.
690 } else {
691 *channel_name = kChromeChannelUnknown;
692 }
693 }
694 #endif // GOOGLE_CHROME_BUILD
695 }
696
697 std::string GetGoogleUpdateVersion() {
698 base::string16 update_version;
699 if (ReadKeyValueString(IsSystemInstall(GetCurrentProcessExePath().c_str()),
700 kRegPathGoogleUpdate,
701 L"",
grt (UTC plus 2) 2016/05/03 15:54:55 nit: nullptr
ananta 2016/05/03 21:40:56 Done.
702 kRegGoogleUpdateVersion,
703 &update_version)) {
704 return utf16_to_utf8(update_version);
705 }
706 return std::string();
707 }
708
709 base::string16 GetChromeInstallSubDirectory() {
710 base::string16 result;
711 #if defined(GOOGLE_CHROME_BUILD)
712 base::string16 sub_directory = kGoogleChromeInstallSubDir1;
grt (UTC plus 2) 2016/05/03 15:54:55 nit: rename this to |result|; do away with line 71
ananta 2016/05/03 21:40:57 Done.
713 sub_directory += L"\\";
714 sub_directory += kGoogleChromeInstallSubDir2;
715 if (IsSxSChrome(GetCurrentProcessExePath().c_str()))
716 sub_directory += kSxSSuffix;
717 return result.append(sub_directory);
718 #else
719 return base::string16(kChromiumInstallSubDir);
720 #endif
721 }
722
723 base::string16 GetBrowserCrashDumpAttemptsRegistryPath() {
724 base::string16 registry_path = L"Software\\";
725 registry_path += GetChromeInstallSubDirectory();
726 registry_path += kBrowserCrashDumpMetricsSubKey;
727 return registry_path;
728 }
729
730 bool MatchPattern(const base::string16& source,
731 const base::string16& pattern) {
732 assert(pattern.find(L"**") == base::string16::npos);
733 return MatchPatternImpl(source, pattern, 0, 0);
734 }
735
736 } // namespace install_static
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698