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

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

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

Powered by Google App Engine
This is Rietveld 408576698