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

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

Issue 2422643002: Windows install_static refactor. (Closed)
Patch Set: sync to position 431863 Created 4 years, 1 month 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 <windows.h>
8 #include <assert.h> 8 #include <assert.h>
9 #include <string.h>
10
9 #include <algorithm> 11 #include <algorithm>
10 #include <iostream>
11 #include <iterator>
12 #include <memory> 12 #include <memory>
13 #include <sstream> 13 #include <sstream>
14 14
15 #include "chrome/install_static/install_details.h"
16 #include "chrome/install_static/install_modes.h"
15 #include "chrome_elf/nt_registry/nt_registry.h" 17 #include "chrome_elf/nt_registry/nt_registry.h"
16 18
17 namespace install_static { 19 namespace install_static {
18 20
19 ProcessType g_process_type = ProcessType::UNINITIALIZED; 21 ProcessType g_process_type = ProcessType::UNINITIALIZED;
20 22
23 const wchar_t kRegValueChromeStatsSample[] = L"UsageStatsInSample";
24
21 // TODO(ananta) 25 // TODO(ananta)
22 // http://crbug.com/604923 26 // http://crbug.com/604923
23 // The constants defined in this file are also defined in chrome/installer and 27 // The constants defined in this file are also defined in chrome/installer and
24 // other places. we need to unify them. 28 // other places. we need to unify them.
25
26 // Chrome channel display names.
27 const wchar_t kChromeChannelUnknown[] = L"unknown";
28 const wchar_t kChromeChannelCanary[] = L"canary";
29 const wchar_t kChromeChannelDev[] = L"dev";
30 const wchar_t kChromeChannelBeta[] = L"beta";
31 const wchar_t kChromeChannelStable[] = L"";
32 const wchar_t kChromeChannelStableExplicit[] = L"stable";
33 const wchar_t kRegApField[] = L"ap";
34
35 #if defined(GOOGLE_CHROME_BUILD)
36 const wchar_t kRegPathClientState[] = L"Software\\Google\\Update\\ClientState";
37 const wchar_t kRegPathClientStateMedium[] =
38 L"Software\\Google\\Update\\ClientStateMedium";
39 const wchar_t kRegPathChromePolicy[] = L"SOFTWARE\\Policies\\Google\\Chrome";
40 #else
41 const wchar_t kRegPathClientState[] =
42 L"Software\\Chromium\\Update\\ClientState";
43 const wchar_t kRegPathClientStateMedium[] =
44 L"Software\\Chromium\\Update\\ClientStateMedium";
45 const wchar_t kRegPathChromePolicy[] = L"SOFTWARE\\Policies\\Chromium";
46 #endif
47
48 const wchar_t kRegValueChromeStatsSample[] = L"UsageStatsInSample";
49 const wchar_t kRegValueUsageStats[] = L"usagestats";
50 const wchar_t kUninstallArgumentsField[] = L"UninstallArguments";
51 const wchar_t kMetricsReportingEnabled[] = L"MetricsReportingEnabled";
52
53 const wchar_t kAppGuidCanary[] = L"{4ea16ac7-fd5a-47c3-875b-dbf4a2008c20}";
54 const wchar_t kAppGuidGoogleChrome[] =
55 L"{8A69D345-D564-463c-AFF1-A69D9E530F96}";
56 const wchar_t kAppGuidGoogleBinaries[] =
57 L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}";
58
59 const wchar_t kHeadless[] = L"CHROME_HEADLESS"; 29 const wchar_t kHeadless[] = L"CHROME_HEADLESS";
60 const wchar_t kShowRestart[] = L"CHROME_CRASHED"; 30 const wchar_t kShowRestart[] = L"CHROME_CRASHED";
61 const wchar_t kRestartInfo[] = L"CHROME_RESTART"; 31 const wchar_t kRestartInfo[] = L"CHROME_RESTART";
62 const wchar_t kRtlLocale[] = L"RIGHT_TO_LEFT"; 32 const wchar_t kRtlLocale[] = L"RIGHT_TO_LEFT";
63 33
64 const char kGpuProcess[] = "gpu-process"; 34 const char kGpuProcess[] = "gpu-process";
65 const char kPpapiPluginProcess[] = "ppapi"; 35 const char kPpapiPluginProcess[] = "ppapi";
66 const char kRendererProcess[] = "renderer"; 36 const char kRendererProcess[] = "renderer";
67 const char kUtilityProcess[] = "utility"; 37 const char kUtilityProcess[] = "utility";
68 const char kProcessType[] = "type"; 38 const char kProcessType[] = "type";
69 const char kCrashpadHandler[] = "crashpad-handler"; 39 const char kCrashpadHandler[] = "crashpad-handler";
70 40
71 namespace { 41 namespace {
72 42
73 // TODO(ananta) 43 // TODO(ananta)
74 // http://crbug.com/604923 44 // http://crbug.com/604923
45 // The constants defined in this file are also defined in chrome/installer and
46 // other places. we need to unify them.
47 // Chrome channel display names.
48 constexpr wchar_t kChromeChannelDev[] = L"dev";
49 constexpr wchar_t kChromeChannelBeta[] = L"beta";
50 constexpr wchar_t kChromeChannelStableExplicit[] = L"stable";
51
52 // TODO(ananta)
53 // http://crbug.com/604923
75 // These constants are defined in the chrome/installer directory as well. We 54 // These constants are defined in the chrome/installer directory as well. We
76 // need to unify them. 55 // need to unify them.
77 #if defined(GOOGLE_CHROME_BUILD) 56 constexpr wchar_t kRegValueAp[] = L"ap";
78 const wchar_t kSxSSuffix[] = L" SxS"; 57 constexpr wchar_t kRegValueUsageStats[] = L"usagestats";
79 const wchar_t kGoogleChromeInstallSubDir1[] = L"Google"; 58 constexpr wchar_t kMetricsReportingEnabled[] = L"MetricsReportingEnabled";
80 const wchar_t kGoogleChromeInstallSubDir2[] = L"Chrome";
81 #else
82 const wchar_t kChromiumInstallSubDir[] = L"Chromium";
83 #endif // defined(GOOGLE_CHROME_BUILD)
84 59
85 const wchar_t kUserDataDirname[] = L"User Data"; 60 constexpr wchar_t kUserDataDirname[] = L"User Data";
86 const wchar_t kBrowserCrashDumpMetricsSubKey[] = L"\\BrowserCrashDumpAttempts"; 61 constexpr wchar_t kBrowserCrashDumpMetricsSubKey[] =
87 62 L"\\BrowserCrashDumpAttempts";
88 const wchar_t kRegPathGoogleUpdate[] = L"Software\\Google\\Update";
89 const wchar_t kRegGoogleUpdateVersion[] = L"version";
90 63
91 void Trace(const wchar_t* format_string, ...) { 64 void Trace(const wchar_t* format_string, ...) {
92 static const int kMaxLogBufferSize = 1024; 65 static const int kMaxLogBufferSize = 1024;
93 static wchar_t buffer[kMaxLogBufferSize] = {}; 66 static wchar_t buffer[kMaxLogBufferSize] = {};
94 67
95 va_list args = {}; 68 va_list args = {};
96 69
97 va_start(args, format_string); 70 va_start(args, format_string);
98 vswprintf(buffer, kMaxLogBufferSize, format_string, args); 71 vswprintf(buffer, kMaxLogBufferSize, format_string, args);
99 OutputDebugStringW(buffer); 72 OutputDebugStringW(buffer);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 uint32_t size = 0; 144 uint32_t size = 0;
172 BOOL r = ::VerQueryValueW(version_resource, sub_block, &value, &size); 145 BOOL r = ::VerQueryValueW(version_resource, sub_block, &value, &size);
173 if (r && value) { 146 if (r && value) {
174 value_str->assign(static_cast<wchar_t*>(value)); 147 value_str->assign(static_cast<wchar_t*>(value));
175 return true; 148 return true;
176 } 149 }
177 } 150 }
178 return false; 151 return false;
179 } 152 }
180 153
181 // Returns the executable path for the current process.
182 std::wstring GetCurrentProcessExePath() {
183 wchar_t exe_path[MAX_PATH];
184 if (::GetModuleFileName(nullptr, exe_path, MAX_PATH) == 0)
185 return std::wstring();
186 return exe_path;
187 }
188
189 bool RecursiveDirectoryCreate(const std::wstring& full_path) { 154 bool RecursiveDirectoryCreate(const std::wstring& full_path) {
190 // If the path exists, we've succeeded if it's a directory, failed otherwise. 155 // If the path exists, we've succeeded if it's a directory, failed otherwise.
191 const wchar_t* full_path_str = full_path.c_str(); 156 const wchar_t* full_path_str = full_path.c_str();
192 DWORD file_attributes = ::GetFileAttributes(full_path_str); 157 DWORD file_attributes = ::GetFileAttributes(full_path_str);
193 if (file_attributes != INVALID_FILE_ATTRIBUTES) { 158 if (file_attributes != INVALID_FILE_ATTRIBUTES) {
194 if ((file_attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { 159 if ((file_attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
195 Trace(L"%hs( %ls directory exists )\n", __func__, full_path_str); 160 Trace(L"%hs( %ls directory exists )\n", __func__, full_path_str);
196 return true; 161 return true;
197 } 162 }
198 Trace(L"%hs( %ls directory conflicts with an existing file. )\n", __func__, 163 Trace(L"%hs( %ls directory conflicts with an existing file. )\n", __func__,
(...skipping 29 matching lines...) Expand all
228 } else { 193 } else {
229 Trace(L"Failed to create directory %ls, last error is %d\n", 194 Trace(L"Failed to create directory %ls, last error is %d\n",
230 full_path_str, error_code); 195 full_path_str, error_code);
231 return false; 196 return false;
232 } 197 }
233 } 198 }
234 } 199 }
235 return true; 200 return true;
236 } 201 }
237 202
203 // Appends "[kCompanyPathName\]kProductPathName[install_suffix]" to |path|,
204 // returning a reference to |path|.
205 std::wstring& AppendChromeInstallSubDirectory(std::wstring* path,
206 bool include_suffix) {
207 if (*kCompanyPathName) {
208 path->append(kCompanyPathName);
209 path->push_back(L'\\');
210 }
211 path->append(kProductPathName, kProductPathNameLength);
212 if (!include_suffix)
213 return *path;
214 return path->append(InstallDetails::Get().install_suffix());
215 }
216
238 std::wstring GetChromeInstallRegistryPath() { 217 std::wstring GetChromeInstallRegistryPath() {
239 std::wstring registry_path = L"Software\\"; 218 std::wstring registry_path = L"Software\\";
240 registry_path += GetChromeInstallSubDirectory(); 219 return AppendChromeInstallSubDirectory(&registry_path,
241 return registry_path; 220 true /* include_suffix */);
242 }
243
244 bool GetCollectStatsConsentImpl(const std::wstring& exe_path) {
245 bool enabled = true;
246
247 if (ReportingIsEnforcedByPolicy(&enabled))
248 return enabled;
249
250 bool system_install = IsSystemInstall(exe_path.c_str());
251 std::wstring app_guid;
252
253 if (IsSxSChrome(exe_path.c_str())) {
254 app_guid = kAppGuidCanary;
255 } else {
256 app_guid = IsMultiInstall(system_install) ? kAppGuidGoogleBinaries
257 : kAppGuidGoogleChrome;
258 }
259
260 DWORD out_value = 0;
261
262 // If system_install, first try kRegPathClientStateMedium.
263 std::wstring full_key_path(kRegPathClientStateMedium);
264 full_key_path.append(1, L'\\');
265 full_key_path.append(app_guid);
266 if (system_install &&
267 nt::QueryRegValueDWORD(nt::HKLM, nt::WOW6432, full_key_path.c_str(),
268 kRegValueUsageStats, &out_value))
269 return (out_value == 1);
270
271 // Second, try kRegPathClientState.
272 full_key_path = kRegPathClientState;
273 full_key_path.append(1, L'\\');
274 full_key_path.append(app_guid);
275 return (nt::QueryRegValueDWORD((system_install ? nt::HKLM : nt::HKCU),
276 nt::WOW6432, full_key_path.c_str(),
277 kRegValueUsageStats, &out_value) &&
278 out_value == 1);
279 } 221 }
280 222
281 // Returns true if the |source| string matches the |pattern|. The pattern 223 // Returns true if the |source| string matches the |pattern|. The pattern
282 // may contain wildcards like '?' which matches one character or a '*' 224 // may contain wildcards like '?' which matches one character or a '*'
283 // which matches 0 or more characters. 225 // which matches 0 or more characters.
284 // Please note that pattern matches the whole string. If you want to find 226 // Please note that pattern matches the whole string. If you want to find
285 // something in the middle of the string then you need to specify the pattern 227 // something in the middle of the string then you need to specify the pattern
286 // as '*xyz*'. 228 // as '*xyz*'.
287 // |source_index| is the index of the current character being matched in 229 // |source_index| is the index of the current character being matched in
288 // |source|. 230 // |source|.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 return kWhiteSpaces; 289 return kWhiteSpaces;
348 } 290 }
349 291
350 // Trim whitespaces from left & right 292 // Trim whitespaces from left & right
351 template <class StringType> 293 template <class StringType>
352 void TrimT(StringType* str) { 294 void TrimT(StringType* str) {
353 str->erase(str->find_last_not_of(GetWhiteSpacesForType<StringType>()) + 1); 295 str->erase(str->find_last_not_of(GetWhiteSpacesForType<StringType>()) + 1);
354 str->erase(0, str->find_first_not_of(GetWhiteSpacesForType<StringType>())); 296 str->erase(0, str->find_first_not_of(GetWhiteSpacesForType<StringType>()));
355 } 297 }
356 298
357 bool IsValidNumber(const std::string& str) {
358 if (str.empty())
359 return false;
360 return std::all_of(str.begin(), str.end(), ::isdigit);
361 }
362
363 // Tokenizes a string based on a single character delimiter. 299 // Tokenizes a string based on a single character delimiter.
364 template <class StringType> 300 template <class StringType>
365 std::vector<StringType> TokenizeStringT( 301 std::vector<StringType> TokenizeStringT(
366 const StringType& str, 302 const StringType& str,
367 typename StringType::value_type delimiter, 303 typename StringType::value_type delimiter,
368 bool trim_spaces) { 304 bool trim_spaces) {
369 std::vector<StringType> tokens; 305 std::vector<StringType> tokens;
370 std::basic_istringstream<typename StringType::value_type> buffer(str); 306 std::basic_istringstream<typename StringType::value_type> buffer(str);
371 for (StringType token; std::getline(buffer, token, delimiter);) { 307 for (StringType token; std::getline(buffer, token, delimiter);) {
372 if (trim_spaces) 308 if (trim_spaces)
373 TrimT<StringType>(&token); 309 TrimT<StringType>(&token);
374 tokens.push_back(token); 310 tokens.push_back(token);
375 } 311 }
376 return tokens; 312 return tokens;
377 } 313 }
378 314
315 std::wstring ChannelFromAdditionalParameters(const InstallConstants& mode,
316 bool system_level,
317 bool binaries) {
318 assert(kUseGoogleUpdateIntegration);
319 // InitChannelInfo in google_update_settings.cc only reports a failure in the
320 // case of multi-install Chrome where the binaries' ClientState key exists,
321 // but that the "ap" value therein cannot be read due to some reason *other*
322 // than it not being present. This should be exceedingly rare. For
323 // simplicity's sake, use an empty |value| in case of any error whatsoever
324 // here.
325 std::wstring value;
326 nt::QueryRegValueSZ(system_level ? nt::HKLM : nt::HKCU, nt::WOW6432,
327 (binaries ? GetBinariesClientStateKeyPath()
328 : GetClientStateKeyPath(mode.app_guid))
329 .c_str(),
330 kRegValueAp, &value);
331
332 static constexpr wchar_t kChromeChannelBetaPattern[] = L"1?1-*";
333 static constexpr wchar_t kChromeChannelBetaX64Pattern[] = L"*x64-beta*";
334 static constexpr wchar_t kChromeChannelDevPattern[] = L"2?0-d*";
335 static constexpr wchar_t kChromeChannelDevX64Pattern[] = L"*x64-dev*";
336
337 std::transform(value.begin(), value.end(), value.begin(), ::tolower);
338
339 // Empty channel names or those containing "stable" should be reported as
340 // an empty string.
341 std::wstring channel_name;
342 if (value.empty() ||
343 (value.find(kChromeChannelStableExplicit) != std::wstring::npos)) {
344 } else if (MatchPattern(value, kChromeChannelDevPattern) ||
345 MatchPattern(value, kChromeChannelDevX64Pattern)) {
346 channel_name.assign(kChromeChannelDev);
347 } else if (MatchPattern(value, kChromeChannelBetaPattern) ||
348 MatchPattern(value, kChromeChannelBetaX64Pattern)) {
349 channel_name.assign(kChromeChannelBeta);
350 }
351 // Else report values with garbage as stable since they will match the stable
352 // rules in the update configs. ChannelInfo::GetChannelName painstakingly
353 // strips off known modifiers (e.g., "-multi-full") to see if the empty string
354 // remains, returning channel "unknown" if not. This differs here in that some
355 // clients will tag crashes as "stable" rather than "unknown" via this
356 // codepath, but it is an accurate reflection of which update channel the
357 // client is on according to the server-side rules.
358
359 return channel_name;
360 }
361
379 } // namespace 362 } // namespace
380 363
381 bool IsSxSChrome(const wchar_t* exe_path) { 364 bool IsSystemInstall() {
382 return ::wcsstr(exe_path, L"Chrome SxS\\Application") != nullptr; 365 return InstallDetails::Get().system_level();
383 } 366 }
384 367
385 bool IsSystemInstall(const wchar_t* exe_path) { 368 bool IsMultiInstall() {
386 wchar_t program_dir[MAX_PATH] = {}; 369 return InstallDetails::Get().multi_install();
387 DWORD ret = ::GetEnvironmentVariable(L"PROGRAMFILES", program_dir, MAX_PATH);
388 if (ret && ret < MAX_PATH && !::wcsnicmp(exe_path, program_dir, ret)) {
389 return true;
390 }
391
392 ret = ::GetEnvironmentVariable(L"PROGRAMFILES(X86)", program_dir, MAX_PATH);
393 if (ret && ret < MAX_PATH && !::wcsnicmp(exe_path, program_dir, ret)) {
394 return true;
395 }
396
397 return false;
398 }
399
400 bool IsMultiInstall(bool is_system_install) {
401 std::wstring args;
402
403 std::wstring full_key_path(kRegPathClientState);
404 full_key_path.append(1, L'\\');
405 full_key_path.append(kAppGuidGoogleChrome);
406 if (!nt::QueryRegValueSZ((is_system_install ? nt::HKLM : nt::HKCU),
407 nt::WOW6432, full_key_path.c_str(),
408 kUninstallArgumentsField, &args))
409 return false;
410
411 return (args.find(L"--multi-install") != std::wstring::npos);
412 } 370 }
413 371
414 bool GetCollectStatsConsent() { 372 bool GetCollectStatsConsent() {
415 return GetCollectStatsConsentImpl(GetCurrentProcessExePath()); 373 bool enabled = true;
416 }
417 374
418 bool GetCollectStatsConsentForTesting(const std::wstring& exe_path) { 375 if (ReportingIsEnforcedByPolicy(&enabled))
419 return GetCollectStatsConsentImpl(exe_path); 376 return enabled;
377
378 const bool system_install = IsSystemInstall();
379
380 DWORD out_value = 0;
381
382 // If system_install, first try ClientStateMedium in HKLM.
383 if (system_install &&
384 nt::QueryRegValueDWORD(
385 nt::HKLM, nt::WOW6432,
386 InstallDetails::Get().GetClientStateMediumKeyPath(true).c_str(),
387 kRegValueUsageStats, &out_value)) {
388 return (out_value == 1);
389 }
390
391 // Second, try ClientState.
392 return (nt::QueryRegValueDWORD(
393 system_install ? nt::HKLM : nt::HKCU, nt::WOW6432,
394 InstallDetails::Get().GetClientStateKeyPath(true).c_str(),
395 kRegValueUsageStats, &out_value) &&
396 out_value == 1);
420 } 397 }
421 398
422 bool GetCollectStatsInSample() { 399 bool GetCollectStatsInSample() {
423 std::wstring registry_path = GetChromeInstallRegistryPath(); 400 std::wstring registry_path = GetChromeInstallRegistryPath();
424 401
425 DWORD out_value = 0; 402 DWORD out_value = 0;
426 if (!nt::QueryRegValueDWORD(nt::HKCU, nt::WOW6432, registry_path.c_str(), 403 if (!nt::QueryRegValueDWORD(nt::HKCU, nt::WOW6432, registry_path.c_str(),
427 kRegValueChromeStatsSample, &out_value)) { 404 kRegValueChromeStatsSample, &out_value)) {
428 // If reading the value failed, treat it as though sampling isn't in effect, 405 // If reading the value failed, treat it as though sampling isn't in effect,
429 // implicitly meaning this install is in the sample. 406 // implicitly meaning this install is in the sample.
430 return true; 407 return true;
431 } 408 }
432 return out_value == 1; 409 return out_value == 1;
433 } 410 }
434 411
435 bool SetCollectStatsInSample(bool in_sample) { 412 bool SetCollectStatsInSample(bool in_sample) {
436 std::wstring registry_path = GetChromeInstallRegistryPath(); 413 std::wstring registry_path = GetChromeInstallRegistryPath();
437 414
438 HANDLE key_handle = INVALID_HANDLE_VALUE; 415 HANDLE key_handle = INVALID_HANDLE_VALUE;
439 if (!nt::CreateRegKey(nt::HKCU, registry_path.c_str(), 416 if (!nt::CreateRegKey(nt::HKCU, registry_path.c_str(),
440 KEY_SET_VALUE | KEY_WOW64_32KEY, &key_handle)) { 417 KEY_SET_VALUE | KEY_WOW64_32KEY, &key_handle)) {
441 nt::CloseRegKey(key_handle);
442 return false; 418 return false;
443 } 419 }
444 420
445 return nt::SetRegValueDWORD(key_handle, kRegValueChromeStatsSample, 421 bool success = nt::SetRegValueDWORD(key_handle, kRegValueChromeStatsSample,
446 in_sample ? 1 : 0); 422 in_sample ? 1 : 0);
423 nt::CloseRegKey(key_handle);
424 return success;
447 } 425 }
448 426
449 bool ReportingIsEnforcedByPolicy(bool* crash_reporting_enabled) { 427 bool ReportingIsEnforcedByPolicy(bool* crash_reporting_enabled) {
428 std::wstring policies_path = L"SOFTWARE\\Policies\\";
429 AppendChromeInstallSubDirectory(&policies_path, false /* !include_suffix */);
450 DWORD value = 0; 430 DWORD value = 0;
451 431
452 // First, try HKLM. 432 // First, try HKLM.
453 if (nt::QueryRegValueDWORD(nt::HKLM, nt::NONE, kRegPathChromePolicy, 433 if (nt::QueryRegValueDWORD(nt::HKLM, nt::NONE, policies_path.c_str(),
454 kMetricsReportingEnabled, &value)) { 434 kMetricsReportingEnabled, &value)) {
455 *crash_reporting_enabled = (value != 0); 435 *crash_reporting_enabled = (value != 0);
456 return true; 436 return true;
457 } 437 }
458 438
459 // Second, try HKCU. 439 // Second, try HKCU.
460 if (nt::QueryRegValueDWORD(nt::HKCU, nt::NONE, kRegPathChromePolicy, 440 if (nt::QueryRegValueDWORD(nt::HKCU, nt::NONE, policies_path.c_str(),
461 kMetricsReportingEnabled, &value)) { 441 kMetricsReportingEnabled, &value)) {
462 *crash_reporting_enabled = (value != 0); 442 *crash_reporting_enabled = (value != 0);
463 return true; 443 return true;
464 } 444 }
465 445
466 return false; 446 return false;
467 } 447 }
468 448
469 void InitializeProcessType() { 449 void InitializeProcessType() {
470 assert(g_process_type == ProcessType::UNINITIALIZED); 450 assert(g_process_type == ProcessType::UNINITIALIZED);
(...skipping 16 matching lines...) Expand all
487 467
488 g_process_type = ProcessType::BROWSER_PROCESS; 468 g_process_type = ProcessType::BROWSER_PROCESS;
489 } 469 }
490 470
491 bool IsNonBrowserProcess() { 471 bool IsNonBrowserProcess() {
492 assert(g_process_type != ProcessType::UNINITIALIZED); 472 assert(g_process_type != ProcessType::UNINITIALIZED);
493 return g_process_type == ProcessType::NON_BROWSER_PROCESS; 473 return g_process_type == ProcessType::NON_BROWSER_PROCESS;
494 } 474 }
495 475
496 bool GetDefaultUserDataDirectory(std::wstring* result) { 476 bool GetDefaultUserDataDirectory(std::wstring* result) {
497 static const wchar_t kLocalAppData[] = L"%LOCALAPPDATA%"; 477 // This environment variable should be set on Windows Vista and later
478 // (https://msdn.microsoft.com/library/windows/desktop/dd378457.aspx).
479 std::wstring user_data_dir = GetEnvironmentString16(L"LOCALAPPDATA");
498 480
499 std::unique_ptr<wchar_t> user_data_dir_path; 481 if (user_data_dir.empty()) {
500 482 // LOCALAPPDATA was not set; fallback to the temporary files path.
501 // This environment variable should be set on Windows 7 and up. 483 DWORD size = ::GetTempPath(0, nullptr);
502 // If we fail to find this variable then we default to the temporary files
503 // path.
504 DWORD size = ::ExpandEnvironmentStrings(kLocalAppData, nullptr, 0);
505 if (size) {
506 user_data_dir_path.reset(new wchar_t[size]);
507 if (::ExpandEnvironmentStrings(kLocalAppData, user_data_dir_path.get(),
508 size) != size) {
509 user_data_dir_path.reset();
510 }
511 }
512 // We failed to find the %LOCALAPPDATA% folder. Fallback to the temporary
513 // files path. If we fail to find this we bail.
514 if (!user_data_dir_path.get()) {
515 size = ::GetTempPath(0, nullptr);
516 if (!size) 484 if (!size)
517 return false; 485 return false;
518 user_data_dir_path.reset(new wchar_t[size + 1]); 486 user_data_dir.resize(size + 1);
519 if (::GetTempPath(size + 1, user_data_dir_path.get()) != size) 487 size = ::GetTempPath(size + 1, &user_data_dir[0]);
488 if (!size || size >= user_data_dir.size())
520 return false; 489 return false;
490 user_data_dir.resize(size);
521 } 491 }
522 492
523 std::wstring install_sub_directory = GetChromeInstallSubDirectory(); 493 result->swap(user_data_dir);
524
525 *result = user_data_dir_path.get();
526 if ((*result)[result->length() - 1] != L'\\') 494 if ((*result)[result->length() - 1] != L'\\')
527 result->append(L"\\"); 495 result->push_back(L'\\');
528 result->append(install_sub_directory); 496 AppendChromeInstallSubDirectory(result, true /* include_suffix */);
529 result->append(L"\\"); 497 result->push_back(L'\\');
530 result->append(kUserDataDirname); 498 result->append(kUserDataDirname);
531 return true; 499 return true;
532 } 500 }
533 501
534 bool GetDefaultCrashDumpLocation(std::wstring* crash_dir) { 502 bool GetDefaultCrashDumpLocation(std::wstring* crash_dir) {
535 // In order to be able to start crash handling very early, we do not rely on 503 // In order to be able to start crash handling very early, we do not rely on
536 // chrome's PathService entries (for DIR_CRASH_DUMPS) being available on 504 // chrome's PathService entries (for DIR_CRASH_DUMPS) being available on
537 // Windows. See https://crbug.com/564398. 505 // Windows. See https://crbug.com/564398.
538 if (!GetDefaultUserDataDirectory(crash_dir)) 506 if (!GetDefaultUserDataDirectory(crash_dir))
539 return false; 507 return false;
540 508
541 // We have to make sure the user data dir exists on first run. See 509 // We have to make sure the user data dir exists on first run. See
542 // http://crbug.com/591504. 510 // http://crbug.com/591504.
543 if (!RecursiveDirectoryCreate(crash_dir->c_str())) 511 if (!RecursiveDirectoryCreate(*crash_dir))
544 return false; 512 return false;
545 crash_dir->append(L"\\Crashpad"); 513 crash_dir->append(L"\\Crashpad");
546 return true; 514 return true;
547 } 515 }
548 516
549 std::string GetEnvironmentString(const std::string& variable_name) { 517 std::string GetEnvironmentString(const std::string& variable_name) {
550 return UTF16ToUTF8(GetEnvironmentString16(UTF8ToUTF16(variable_name))); 518 return UTF16ToUTF8(
519 GetEnvironmentString16(UTF8ToUTF16(variable_name).c_str()));
551 } 520 }
552 521
553 std::wstring GetEnvironmentString16(const std::wstring& variable_name) { 522 std::wstring GetEnvironmentString16(const wchar_t* variable_name) {
554 DWORD value_length = 523 DWORD value_length = ::GetEnvironmentVariableW(variable_name, nullptr, 0);
555 ::GetEnvironmentVariable(variable_name.c_str(), nullptr, 0); 524 if (!value_length)
556 if (value_length == 0)
557 return std::wstring(); 525 return std::wstring();
558 std::unique_ptr<wchar_t[]> value(new wchar_t[value_length]); 526 std::wstring value(value_length, L'\0');
559 ::GetEnvironmentVariable(variable_name.c_str(), value.get(), value_length); 527 value_length =
560 return value.get(); 528 ::GetEnvironmentVariableW(variable_name, &value[0], value_length);
529 if (!value_length || value_length >= value.size())
530 return std::wstring();
531 value.resize(value_length);
532 return value;
561 } 533 }
562 534
563 bool SetEnvironmentString(const std::string& variable_name, 535 bool SetEnvironmentString(const std::string& variable_name,
564 const std::string& new_value) { 536 const std::string& new_value) {
565 return SetEnvironmentString16(UTF8ToUTF16(variable_name), 537 return SetEnvironmentString16(UTF8ToUTF16(variable_name),
566 UTF8ToUTF16(new_value)); 538 UTF8ToUTF16(new_value));
567 } 539 }
568 540
569 bool SetEnvironmentString16(const std::wstring& variable_name, 541 bool SetEnvironmentString16(const std::wstring& variable_name,
570 const std::wstring& new_value) { 542 const std::wstring& new_value) {
571 return !!SetEnvironmentVariable(variable_name.c_str(), new_value.c_str()); 543 return !!SetEnvironmentVariable(variable_name.c_str(), new_value.c_str());
572 } 544 }
573 545
574 bool HasEnvironmentVariable(const std::string& variable_name) { 546 bool HasEnvironmentVariable(const std::string& variable_name) {
575 return HasEnvironmentVariable16(UTF8ToUTF16(variable_name)); 547 return HasEnvironmentVariable16(UTF8ToUTF16(variable_name));
576 } 548 }
577 549
578 bool HasEnvironmentVariable16(const std::wstring& variable_name) { 550 bool HasEnvironmentVariable16(const std::wstring& variable_name) {
579 return !!::GetEnvironmentVariable(variable_name.c_str(), nullptr, 0); 551 return !!::GetEnvironmentVariable(variable_name.c_str(), nullptr, 0);
580 } 552 }
581 553
582 bool GetExecutableVersionDetails(const std::wstring& exe_path, 554 void GetExecutableVersionDetails(const std::wstring& exe_path,
583 std::wstring* product_name, 555 std::wstring* product_name,
584 std::wstring* version, 556 std::wstring* version,
585 std::wstring* special_build, 557 std::wstring* special_build,
586 std::wstring* channel_name) { 558 std::wstring* channel_name) {
587 assert(product_name); 559 assert(product_name);
588 assert(version); 560 assert(version);
589 assert(special_build); 561 assert(special_build);
590 assert(channel_name); 562 assert(channel_name);
591 563
592 // Default values in case we don't find a version resource. 564 // Default values in case we don't find a version resource.
593 *product_name = L"Chrome"; 565 *product_name = L"Chrome";
594 *version = L"0.0.0.0-devel"; 566 *version = L"0.0.0.0-devel";
595 *channel_name = kChromeChannelUnknown;
596 special_build->clear(); 567 special_build->clear();
597 568
598 DWORD dummy = 0; 569 DWORD dummy = 0;
599 DWORD length = ::GetFileVersionInfoSize(exe_path.c_str(), &dummy); 570 DWORD length = ::GetFileVersionInfoSize(exe_path.c_str(), &dummy);
600 if (length) { 571 if (length) {
601 std::unique_ptr<char> data(new char[length]); 572 std::unique_ptr<char> data(new char[length]);
602 if (::GetFileVersionInfo(exe_path.c_str(), dummy, length, data.get())) { 573 if (::GetFileVersionInfo(exe_path.c_str(), dummy, length, data.get())) {
603 GetValueFromVersionResource(data.get(), L"ProductVersion", version); 574 GetValueFromVersionResource(data.get(), L"ProductVersion", version);
604 575
605 std::wstring official_build; 576 std::wstring official_build;
606 GetValueFromVersionResource(data.get(), L"Official Build", 577 GetValueFromVersionResource(data.get(), L"Official Build",
607 &official_build); 578 &official_build);
608 if (official_build != L"1") 579 if (official_build != L"1")
609 version->append(L"-devel"); 580 version->append(L"-devel");
610 GetValueFromVersionResource(data.get(), L"ProductShortName", 581 GetValueFromVersionResource(data.get(), L"ProductShortName",
611 product_name); 582 product_name);
612 GetValueFromVersionResource(data.get(), L"SpecialBuild", special_build); 583 GetValueFromVersionResource(data.get(), L"SpecialBuild", special_build);
613 } 584 }
614 } 585 }
615 GetChromeChannelName(!IsSystemInstall(exe_path.c_str()), true, channel_name); 586 *channel_name = GetChromeChannelName(true /* add_modifier */);
616 return true;
617 } 587 }
618 588
619 void GetChromeChannelName(bool is_per_user_install, 589 std::wstring GetChromeChannelName(bool add_modifier) {
620 bool add_modifier, 590 const std::wstring& channel = InstallDetails::Get().channel();
621 std::wstring* channel_name) { 591 if (!add_modifier || !IsMultiInstall())
622 // See GoogleChromeSxSDistribution::GetChromeChannel. 592 return channel;
623 if (IsSxSChrome(GetCurrentProcessExePath().c_str())) { 593 if (channel.empty())
624 channel_name->assign(kChromeChannelCanary); 594 return L"m";
625 return; 595 return channel + L"-m";
626 }
627
628 // InitChannelInfo in google_update_settings.cc only reports a failure in the
629 // case of multi-install Chrome where the binaries' ClientState key exists,
630 // but that the "ap" value therein cannot be read due to some reason *other*
631 // than it not being present. This should be exceedingly rare. For
632 // simplicity's sake, use an empty |value| in case of any error whatsoever
633 // here.
634 std::wstring value;
635 bool is_multi_install = IsMultiInstall(!is_per_user_install);
636 if (is_multi_install) {
637 std::wstring full_key_path(kRegPathClientState);
638 full_key_path.append(1, L'\\');
639 full_key_path.append(kAppGuidGoogleBinaries);
640 nt::QueryRegValueSZ(is_per_user_install ? nt::HKCU : nt::HKLM, nt::WOW6432,
641 full_key_path.c_str(), kRegApField, &value);
642 } else {
643 std::wstring full_key_path(kRegPathClientState);
644 full_key_path.append(1, L'\\');
645 full_key_path.append(kAppGuidGoogleChrome);
646 nt::QueryRegValueSZ(is_per_user_install ? nt::HKCU : nt::HKLM, nt::WOW6432,
647 full_key_path.c_str(), kRegApField, &value);
648 }
649
650 static constexpr wchar_t kChromeChannelBetaPattern[] = L"1?1-*";
651 static constexpr wchar_t kChromeChannelBetaX64Pattern[] = L"*x64-beta*";
652 static constexpr wchar_t kChromeChannelDevPattern[] = L"2?0-d*";
653 static constexpr wchar_t kChromeChannelDevX64Pattern[] = L"*x64-dev*";
654
655 std::transform(value.begin(), value.end(), value.begin(), ::tolower);
656
657 // Empty channel names or those containing "stable" should be reported as
658 // an empty string (with the optional modifier).
659 if (value.empty() ||
660 (value.find(kChromeChannelStableExplicit) != std::wstring::npos)) {
661 channel_name->clear();
662 } else if (MatchPattern(value, kChromeChannelDevPattern) ||
663 MatchPattern(value, kChromeChannelDevX64Pattern)) {
664 channel_name->assign(kChromeChannelDev);
665 } else if (MatchPattern(value, kChromeChannelBetaPattern) ||
666 MatchPattern(value, kChromeChannelBetaX64Pattern)) {
667 channel_name->assign(kChromeChannelBeta);
668 } else {
669 // Report values with garbage as stable since they will match the stable
670 // rules in the update configs. ChannelInfo::GetChannelName painstakingly
671 // strips off known modifiers (e.g., "-multi-full") to see if the empty
672 // string remains, returning channel "unknown" if not. This differs here in
673 // that some clients will tag crashes as "stable" rather than "unknown" via
674 // this codepath, but it is an accurate reflection of which update channel
675 // the client is on according to the server-side rules.
676 channel_name->clear();
677 }
678
679 // Tag the channel name if this is a multi-install.
680 if (add_modifier && is_multi_install) {
681 if (!channel_name->empty())
682 channel_name->push_back(L'-');
683 channel_name->push_back(L'm');
684 }
685 }
686
687 std::string GetGoogleUpdateVersion() {
688 // TODO(ananta)
689 // Consider whether Chromium should connect to Google update to manage
690 // updates. Should this be returning an empty string for Chromium builds?.
691 std::wstring update_version;
692 if (nt::QueryRegValueSZ(nt::AUTO, nt::WOW6432, kRegPathGoogleUpdate,
693 kRegGoogleUpdateVersion, &update_version))
694 return UTF16ToUTF8(update_version);
695
696 return std::string();
697 }
698
699 std::wstring GetChromeInstallSubDirectory() {
700 #if defined(GOOGLE_CHROME_BUILD)
701 std::wstring result = kGoogleChromeInstallSubDir1;
702 result += L"\\";
703 result += kGoogleChromeInstallSubDir2;
704 if (IsSxSChrome(GetCurrentProcessExePath().c_str()))
705 result += kSxSSuffix;
706 return result;
707 #else
708 return std::wstring(kChromiumInstallSubDir);
709 #endif
710 } 596 }
711 597
712 std::wstring GetBrowserCrashDumpAttemptsRegistryPath() { 598 std::wstring GetBrowserCrashDumpAttemptsRegistryPath() {
713 std::wstring registry_path = GetChromeInstallRegistryPath(); 599 return GetChromeInstallRegistryPath().append(kBrowserCrashDumpMetricsSubKey);
714 registry_path += kBrowserCrashDumpMetricsSubKey;
715 return registry_path;
716 } 600 }
717 601
718 bool MatchPattern(const std::wstring& source, const std::wstring& pattern) { 602 bool MatchPattern(const std::wstring& source, const std::wstring& pattern) {
719 assert(pattern.find(L"**") == std::wstring::npos); 603 assert(pattern.find(L"**") == std::wstring::npos);
720 return MatchPatternImpl(source, pattern, 0, 0); 604 return MatchPatternImpl(source, pattern, 0, 0);
721 } 605 }
722 606
723 std::string UTF16ToUTF8(const std::wstring& source) { 607 std::string UTF16ToUTF8(const std::wstring& source) {
724 if (source.empty() || 608 if (source.empty() ||
725 static_cast<int>(source.size()) > std::numeric_limits<int>::max()) { 609 static_cast<int>(source.size()) > std::numeric_limits<int>::max()) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
760 bool trim_spaces) { 644 bool trim_spaces) {
761 return TokenizeStringT<std::string>(str, delimiter, trim_spaces); 645 return TokenizeStringT<std::string>(str, delimiter, trim_spaces);
762 } 646 }
763 647
764 std::vector<std::wstring> TokenizeString16(const std::wstring& str, 648 std::vector<std::wstring> TokenizeString16(const std::wstring& str,
765 wchar_t delimiter, 649 wchar_t delimiter,
766 bool trim_spaces) { 650 bool trim_spaces) {
767 return TokenizeStringT<std::wstring>(str, delimiter, trim_spaces); 651 return TokenizeStringT<std::wstring>(str, delimiter, trim_spaces);
768 } 652 }
769 653
770 bool CompareVersionStrings(const std::string& version1,
771 const std::string& version2,
772 int* result) {
773 if (version1.empty() || version2.empty())
774 return false;
775
776 // Tokenize both version strings with "." as the separator. If either of
777 // the returned token lists are empty then bail.
778 std::vector<std::string> version1_components =
779 TokenizeString(version1, '.', false);
780 if (version1_components.empty())
781 return false;
782
783 std::vector<std::string> version2_components =
784 TokenizeString(version2, '.', false);
785 if (version2_components.empty())
786 return false;
787
788 // You may have less tokens in either string. Use the minimum of the number
789 // of tokens as the initial count.
790 const size_t count =
791 std::min(version1_components.size(), version2_components.size());
792 for (size_t i = 0; i < count; ++i) {
793 // If either of the version components don't contain valid numeric digits
794 // bail.
795 if (!IsValidNumber(version1_components[i]) ||
796 !IsValidNumber(version2_components[i])) {
797 return false;
798 }
799
800 int version1_component = std::stoi(version1_components[i]);
801 int version2_component = std::stoi(version2_components[i]);
802
803 if (version1_component > version2_component) {
804 *result = 1;
805 return true;
806 }
807
808 if (version1_component < version2_component) {
809 *result = -1;
810 return true;
811 }
812 }
813
814 // Handle remaining tokens. Here if we have non zero tokens remaining in the
815 // version 1 list then it means that the version1 string is larger. If the
816 // version 1 token list has tokens left, then if either of these tokens is
817 // greater than 0 then it means that the version1 string is smaller than the
818 // version2 string.
819 if (version1_components.size() > version2_components.size()) {
820 for (size_t i = count; i < version1_components.size(); ++i) {
821 // If the version components don't contain valid numeric digits bail.
822 if (!IsValidNumber(version1_components[i]))
823 return false;
824
825 if (std::stoi(version1_components[i]) > 0) {
826 *result = 1;
827 return true;
828 }
829 }
830 } else if (version1_components.size() < version2_components.size()) {
831 for (size_t i = count; i < version2_components.size(); ++i) {
832 // If the version components don't contain valid numeric digits bail.
833 if (!IsValidNumber(version2_components[i]))
834 return false;
835
836 if (std::stoi(version2_components[i]) > 0) {
837 *result = -1;
838 return true;
839 }
840 }
841 }
842 // Here it means that both versions are equal.
843 *result = 0;
844 return true;
845 }
846
847 std::string GetSwitchValueFromCommandLine(const std::string& command_line, 654 std::string GetSwitchValueFromCommandLine(const std::string& command_line,
848 const std::string& switch_name) { 655 const std::string& switch_name) {
849 assert(!command_line.empty()); 656 assert(!command_line.empty());
850 assert(!switch_name.empty()); 657 assert(!switch_name.empty());
851 658
852 std::string command_line_copy = command_line; 659 std::string command_line_copy = command_line;
853 // Remove leading and trailing spaces. 660 // Remove leading and trailing spaces.
854 TrimT<std::string>(&command_line_copy); 661 TrimT<std::string>(&command_line_copy);
855 662
856 // Find the switch in the command line. If we don't find the switch, return 663 // Find the switch in the command line. If we don't find the switch, return
(...skipping 22 matching lines...) Expand all
879 if (switch_value_end_offset == std::string::npos) 686 if (switch_value_end_offset == std::string::npos)
880 switch_value_end_offset = command_line_copy.length(); 687 switch_value_end_offset = command_line_copy.length();
881 688
882 std::string switch_value = command_line_copy.substr( 689 std::string switch_value = command_line_copy.substr(
883 switch_value_start_offset, 690 switch_value_start_offset,
884 switch_value_end_offset - (switch_offset + switch_token.length())); 691 switch_value_end_offset - (switch_offset + switch_token.length()));
885 TrimT<std::string>(&switch_value); 692 TrimT<std::string>(&switch_value);
886 return switch_value; 693 return switch_value;
887 } 694 }
888 695
696 // This function takes these inputs rather than accessing the module's
697 // InstallDetails instance since it is used to bootstrap InstallDetails.
698 std::wstring DetermineChannel(const InstallConstants& mode,
699 bool system_level,
700 bool multi_install) {
701 if (!kUseGoogleUpdateIntegration)
702 return std::wstring();
703
704 switch (mode.channel_strategy) {
705 case ChannelStrategy::UNSUPPORTED:
706 assert(false);
707 break;
708 case ChannelStrategy::ADDITIONAL_PARAMETERS:
709 return ChannelFromAdditionalParameters(mode, system_level, multi_install);
710 case ChannelStrategy::FIXED:
711 return mode.default_channel_name;
712 }
713
714 return std::wstring();
715 }
716
889 } // namespace install_static 717 } // namespace install_static
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698