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

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

Issue 2491463002: Revert of Windows install_static refactor. (Closed)
Patch Set: 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
« no previous file with comments | « chrome/install_static/install_util.h ('k') | chrome/install_static/install_util_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
11 #include <algorithm> 9 #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"
17 #include "chrome_elf/nt_registry/nt_registry.h" 15 #include "chrome_elf/nt_registry/nt_registry.h"
18 16
19 namespace install_static { 17 namespace install_static {
20 18
21 ProcessType g_process_type = ProcessType::UNINITIALIZED; 19 ProcessType g_process_type = ProcessType::UNINITIALIZED;
22 20
23 const wchar_t kRegValueChromeStatsSample[] = L"UsageStatsInSample";
24
25 // TODO(ananta) 21 // TODO(ananta)
26 // http://crbug.com/604923 22 // http://crbug.com/604923
27 // The constants defined in this file are also defined in chrome/installer and 23 // The constants defined in this file are also defined in chrome/installer and
28 // other places. we need to unify them. 24 // 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
29 const wchar_t kHeadless[] = L"CHROME_HEADLESS"; 59 const wchar_t kHeadless[] = L"CHROME_HEADLESS";
30 const wchar_t kShowRestart[] = L"CHROME_CRASHED"; 60 const wchar_t kShowRestart[] = L"CHROME_CRASHED";
31 const wchar_t kRestartInfo[] = L"CHROME_RESTART"; 61 const wchar_t kRestartInfo[] = L"CHROME_RESTART";
32 const wchar_t kRtlLocale[] = L"RIGHT_TO_LEFT"; 62 const wchar_t kRtlLocale[] = L"RIGHT_TO_LEFT";
33 63
34 const char kGpuProcess[] = "gpu-process"; 64 const char kGpuProcess[] = "gpu-process";
35 const char kPpapiPluginProcess[] = "ppapi"; 65 const char kPpapiPluginProcess[] = "ppapi";
36 const char kRendererProcess[] = "renderer"; 66 const char kRendererProcess[] = "renderer";
37 const char kUtilityProcess[] = "utility"; 67 const char kUtilityProcess[] = "utility";
38 const char kProcessType[] = "type"; 68 const char kProcessType[] = "type";
39 const char kCrashpadHandler[] = "crashpad-handler"; 69 const char kCrashpadHandler[] = "crashpad-handler";
40 70
41 namespace { 71 namespace {
42 72
43 // TODO(ananta) 73 // TODO(ananta)
44 // http://crbug.com/604923 74 // 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
54 // These constants are defined in the chrome/installer directory as well. We 75 // These constants are defined in the chrome/installer directory as well. We
55 // need to unify them. 76 // need to unify them.
56 constexpr wchar_t kRegValueAp[] = L"ap"; 77 #if defined(GOOGLE_CHROME_BUILD)
57 constexpr wchar_t kRegValueUsageStats[] = L"usagestats"; 78 const wchar_t kSxSSuffix[] = L" SxS";
58 constexpr wchar_t kMetricsReportingEnabled[] = L"MetricsReportingEnabled"; 79 const wchar_t kGoogleChromeInstallSubDir1[] = L"Google";
80 const wchar_t kGoogleChromeInstallSubDir2[] = L"Chrome";
81 #else
82 const wchar_t kChromiumInstallSubDir[] = L"Chromium";
83 #endif // defined(GOOGLE_CHROME_BUILD)
59 84
60 constexpr wchar_t kUserDataDirname[] = L"User Data"; 85 const wchar_t kUserDataDirname[] = L"User Data";
61 constexpr wchar_t kBrowserCrashDumpMetricsSubKey[] = 86 const wchar_t kBrowserCrashDumpMetricsSubKey[] = L"\\BrowserCrashDumpAttempts";
62 L"\\BrowserCrashDumpAttempts"; 87
88 const wchar_t kRegPathGoogleUpdate[] = L"Software\\Google\\Update";
89 const wchar_t kRegGoogleUpdateVersion[] = L"version";
63 90
64 void Trace(const wchar_t* format_string, ...) { 91 void Trace(const wchar_t* format_string, ...) {
65 static const int kMaxLogBufferSize = 1024; 92 static const int kMaxLogBufferSize = 1024;
66 static wchar_t buffer[kMaxLogBufferSize] = {}; 93 static wchar_t buffer[kMaxLogBufferSize] = {};
67 94
68 va_list args = {}; 95 va_list args = {};
69 96
70 va_start(args, format_string); 97 va_start(args, format_string);
71 vswprintf(buffer, kMaxLogBufferSize, format_string, args); 98 vswprintf(buffer, kMaxLogBufferSize, format_string, args);
72 OutputDebugStringW(buffer); 99 OutputDebugStringW(buffer);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 uint32_t size = 0; 171 uint32_t size = 0;
145 BOOL r = ::VerQueryValueW(version_resource, sub_block, &value, &size); 172 BOOL r = ::VerQueryValueW(version_resource, sub_block, &value, &size);
146 if (r && value) { 173 if (r && value) {
147 value_str->assign(static_cast<wchar_t*>(value)); 174 value_str->assign(static_cast<wchar_t*>(value));
148 return true; 175 return true;
149 } 176 }
150 } 177 }
151 return false; 178 return false;
152 } 179 }
153 180
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
154 bool RecursiveDirectoryCreate(const std::wstring& full_path) { 189 bool RecursiveDirectoryCreate(const std::wstring& full_path) {
155 // If the path exists, we've succeeded if it's a directory, failed otherwise. 190 // If the path exists, we've succeeded if it's a directory, failed otherwise.
156 const wchar_t* full_path_str = full_path.c_str(); 191 const wchar_t* full_path_str = full_path.c_str();
157 DWORD file_attributes = ::GetFileAttributes(full_path_str); 192 DWORD file_attributes = ::GetFileAttributes(full_path_str);
158 if (file_attributes != INVALID_FILE_ATTRIBUTES) { 193 if (file_attributes != INVALID_FILE_ATTRIBUTES) {
159 if ((file_attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { 194 if ((file_attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
160 Trace(L"%hs( %ls directory exists )\n", __func__, full_path_str); 195 Trace(L"%hs( %ls directory exists )\n", __func__, full_path_str);
161 return true; 196 return true;
162 } 197 }
163 Trace(L"%hs( %ls directory conflicts with an existing file. )\n", __func__, 198 Trace(L"%hs( %ls directory conflicts with an existing file. )\n", __func__,
(...skipping 29 matching lines...) Expand all
193 } else { 228 } else {
194 Trace(L"Failed to create directory %ls, last error is %d\n", 229 Trace(L"Failed to create directory %ls, last error is %d\n",
195 full_path_str, error_code); 230 full_path_str, error_code);
196 return false; 231 return false;
197 } 232 }
198 } 233 }
199 } 234 }
200 return true; 235 return true;
201 } 236 }
202 237
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
217 std::wstring GetChromeInstallRegistryPath() { 238 std::wstring GetChromeInstallRegistryPath() {
218 std::wstring registry_path = L"Software\\"; 239 std::wstring registry_path = L"Software\\";
219 return AppendChromeInstallSubDirectory(&registry_path, 240 registry_path += GetChromeInstallSubDirectory();
220 true /* include_suffix */); 241 return registry_path;
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);
221 } 279 }
222 280
223 // Returns true if the |source| string matches the |pattern|. The pattern 281 // Returns true if the |source| string matches the |pattern|. The pattern
224 // may contain wildcards like '?' which matches one character or a '*' 282 // may contain wildcards like '?' which matches one character or a '*'
225 // which matches 0 or more characters. 283 // which matches 0 or more characters.
226 // Please note that pattern matches the whole string. If you want to find 284 // Please note that pattern matches the whole string. If you want to find
227 // something in the middle of the string then you need to specify the pattern 285 // something in the middle of the string then you need to specify the pattern
228 // as '*xyz*'. 286 // as '*xyz*'.
229 // |source_index| is the index of the current character being matched in 287 // |source_index| is the index of the current character being matched in
230 // |source|. 288 // |source|.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 return kWhiteSpaces; 347 return kWhiteSpaces;
290 } 348 }
291 349
292 // Trim whitespaces from left & right 350 // Trim whitespaces from left & right
293 template <class StringType> 351 template <class StringType>
294 void TrimT(StringType* str) { 352 void TrimT(StringType* str) {
295 str->erase(str->find_last_not_of(GetWhiteSpacesForType<StringType>()) + 1); 353 str->erase(str->find_last_not_of(GetWhiteSpacesForType<StringType>()) + 1);
296 str->erase(0, str->find_first_not_of(GetWhiteSpacesForType<StringType>())); 354 str->erase(0, str->find_first_not_of(GetWhiteSpacesForType<StringType>()));
297 } 355 }
298 356
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
299 // Tokenizes a string based on a single character delimiter. 363 // Tokenizes a string based on a single character delimiter.
300 template <class StringType> 364 template <class StringType>
301 std::vector<StringType> TokenizeStringT( 365 std::vector<StringType> TokenizeStringT(
302 const StringType& str, 366 const StringType& str,
303 typename StringType::value_type delimiter, 367 typename StringType::value_type delimiter,
304 bool trim_spaces) { 368 bool trim_spaces) {
305 std::vector<StringType> tokens; 369 std::vector<StringType> tokens;
306 std::basic_istringstream<typename StringType::value_type> buffer(str); 370 std::basic_istringstream<typename StringType::value_type> buffer(str);
307 for (StringType token; std::getline(buffer, token, delimiter);) { 371 for (StringType token; std::getline(buffer, token, delimiter);) {
308 if (trim_spaces) 372 if (trim_spaces)
309 TrimT<StringType>(&token); 373 TrimT<StringType>(&token);
310 tokens.push_back(token); 374 tokens.push_back(token);
311 } 375 }
312 return tokens; 376 return tokens;
313 } 377 }
314 378
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
362 } // namespace 379 } // namespace
363 380
364 bool IsSystemInstall() { 381 bool IsSxSChrome(const wchar_t* exe_path) {
365 return InstallDetails::Get().system_level(); 382 return ::wcsstr(exe_path, L"Chrome SxS\\Application") != nullptr;
366 } 383 }
367 384
368 bool IsMultiInstall() { 385 bool IsSystemInstall(const wchar_t* exe_path) {
369 return InstallDetails::Get().multi_install(); 386 wchar_t program_dir[MAX_PATH] = {};
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);
370 } 412 }
371 413
372 bool GetCollectStatsConsent() { 414 bool GetCollectStatsConsent() {
373 bool enabled = true; 415 return GetCollectStatsConsentImpl(GetCurrentProcessExePath());
416 }
374 417
375 if (ReportingIsEnforcedByPolicy(&enabled)) 418 bool GetCollectStatsConsentForTesting(const std::wstring& exe_path) {
376 return enabled; 419 return GetCollectStatsConsentImpl(exe_path);
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);
397 } 420 }
398 421
399 bool GetCollectStatsInSample() { 422 bool GetCollectStatsInSample() {
400 std::wstring registry_path = GetChromeInstallRegistryPath(); 423 std::wstring registry_path = GetChromeInstallRegistryPath();
401 424
402 DWORD out_value = 0; 425 DWORD out_value = 0;
403 if (!nt::QueryRegValueDWORD(nt::HKCU, nt::WOW6432, registry_path.c_str(), 426 if (!nt::QueryRegValueDWORD(nt::HKCU, nt::WOW6432, registry_path.c_str(),
404 kRegValueChromeStatsSample, &out_value)) { 427 kRegValueChromeStatsSample, &out_value)) {
405 // If reading the value failed, treat it as though sampling isn't in effect, 428 // If reading the value failed, treat it as though sampling isn't in effect,
406 // implicitly meaning this install is in the sample. 429 // implicitly meaning this install is in the sample.
407 return true; 430 return true;
408 } 431 }
409 return out_value == 1; 432 return out_value == 1;
410 } 433 }
411 434
412 bool SetCollectStatsInSample(bool in_sample) { 435 bool SetCollectStatsInSample(bool in_sample) {
413 std::wstring registry_path = GetChromeInstallRegistryPath(); 436 std::wstring registry_path = GetChromeInstallRegistryPath();
414 437
415 HANDLE key_handle = INVALID_HANDLE_VALUE; 438 HANDLE key_handle = INVALID_HANDLE_VALUE;
416 if (!nt::CreateRegKey(nt::HKCU, registry_path.c_str(), 439 if (!nt::CreateRegKey(nt::HKCU, registry_path.c_str(),
417 KEY_SET_VALUE | KEY_WOW64_32KEY, &key_handle)) { 440 KEY_SET_VALUE | KEY_WOW64_32KEY, &key_handle)) {
441 nt::CloseRegKey(key_handle);
418 return false; 442 return false;
419 } 443 }
420 444
421 bool success = nt::SetRegValueDWORD(key_handle, kRegValueChromeStatsSample, 445 return nt::SetRegValueDWORD(key_handle, kRegValueChromeStatsSample,
422 in_sample ? 1 : 0); 446 in_sample ? 1 : 0);
423 nt::CloseRegKey(key_handle);
424 return success;
425 } 447 }
426 448
427 bool ReportingIsEnforcedByPolicy(bool* crash_reporting_enabled) { 449 bool ReportingIsEnforcedByPolicy(bool* crash_reporting_enabled) {
428 std::wstring policies_path = L"SOFTWARE\\Policies\\";
429 AppendChromeInstallSubDirectory(&policies_path, false /* !include_suffix */);
430 DWORD value = 0; 450 DWORD value = 0;
431 451
432 // First, try HKLM. 452 // First, try HKLM.
433 if (nt::QueryRegValueDWORD(nt::HKLM, nt::NONE, policies_path.c_str(), 453 if (nt::QueryRegValueDWORD(nt::HKLM, nt::NONE, kRegPathChromePolicy,
434 kMetricsReportingEnabled, &value)) { 454 kMetricsReportingEnabled, &value)) {
435 *crash_reporting_enabled = (value != 0); 455 *crash_reporting_enabled = (value != 0);
436 return true; 456 return true;
437 } 457 }
438 458
439 // Second, try HKCU. 459 // Second, try HKCU.
440 if (nt::QueryRegValueDWORD(nt::HKCU, nt::NONE, policies_path.c_str(), 460 if (nt::QueryRegValueDWORD(nt::HKCU, nt::NONE, kRegPathChromePolicy,
441 kMetricsReportingEnabled, &value)) { 461 kMetricsReportingEnabled, &value)) {
442 *crash_reporting_enabled = (value != 0); 462 *crash_reporting_enabled = (value != 0);
443 return true; 463 return true;
444 } 464 }
445 465
446 return false; 466 return false;
447 } 467 }
448 468
449 void InitializeProcessType() { 469 void InitializeProcessType() {
450 assert(g_process_type == ProcessType::UNINITIALIZED); 470 assert(g_process_type == ProcessType::UNINITIALIZED);
(...skipping 16 matching lines...) Expand all
467 487
468 g_process_type = ProcessType::BROWSER_PROCESS; 488 g_process_type = ProcessType::BROWSER_PROCESS;
469 } 489 }
470 490
471 bool IsNonBrowserProcess() { 491 bool IsNonBrowserProcess() {
472 assert(g_process_type != ProcessType::UNINITIALIZED); 492 assert(g_process_type != ProcessType::UNINITIALIZED);
473 return g_process_type == ProcessType::NON_BROWSER_PROCESS; 493 return g_process_type == ProcessType::NON_BROWSER_PROCESS;
474 } 494 }
475 495
476 bool GetDefaultUserDataDirectory(std::wstring* result) { 496 bool GetDefaultUserDataDirectory(std::wstring* result) {
477 // This environment variable should be set on Windows Vista and later 497 static const wchar_t kLocalAppData[] = L"%LOCALAPPDATA%";
478 // (https://msdn.microsoft.com/library/windows/desktop/dd378457.aspx).
479 std::wstring user_data_dir = GetEnvironmentString16(L"LOCALAPPDATA");
480 498
481 if (user_data_dir.empty()) { 499 std::unique_ptr<wchar_t> user_data_dir_path;
482 // LOCALAPPDATA was not set; fallback to the temporary files path. 500
483 DWORD size = ::GetTempPath(0, nullptr); 501 // This environment variable should be set on Windows 7 and up.
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);
484 if (!size) 516 if (!size)
485 return false; 517 return false;
486 user_data_dir.resize(size + 1); 518 user_data_dir_path.reset(new wchar_t[size + 1]);
487 size = ::GetTempPath(size + 1, &user_data_dir[0]); 519 if (::GetTempPath(size + 1, user_data_dir_path.get()) != size)
488 if (!size || size >= user_data_dir.size())
489 return false; 520 return false;
490 user_data_dir.resize(size);
491 } 521 }
492 522
493 result->swap(user_data_dir); 523 std::wstring install_sub_directory = GetChromeInstallSubDirectory();
524
525 *result = user_data_dir_path.get();
494 if ((*result)[result->length() - 1] != L'\\') 526 if ((*result)[result->length() - 1] != L'\\')
495 result->push_back(L'\\'); 527 result->append(L"\\");
496 AppendChromeInstallSubDirectory(result, true /* include_suffix */); 528 result->append(install_sub_directory);
497 result->push_back(L'\\'); 529 result->append(L"\\");
498 result->append(kUserDataDirname); 530 result->append(kUserDataDirname);
499 return true; 531 return true;
500 } 532 }
501 533
502 bool GetDefaultCrashDumpLocation(std::wstring* crash_dir) { 534 bool GetDefaultCrashDumpLocation(std::wstring* crash_dir) {
503 // In order to be able to start crash handling very early, we do not rely on 535 // In order to be able to start crash handling very early, we do not rely on
504 // chrome's PathService entries (for DIR_CRASH_DUMPS) being available on 536 // chrome's PathService entries (for DIR_CRASH_DUMPS) being available on
505 // Windows. See https://crbug.com/564398. 537 // Windows. See https://crbug.com/564398.
506 if (!GetDefaultUserDataDirectory(crash_dir)) 538 if (!GetDefaultUserDataDirectory(crash_dir))
507 return false; 539 return false;
508 540
509 // We have to make sure the user data dir exists on first run. See 541 // We have to make sure the user data dir exists on first run. See
510 // http://crbug.com/591504. 542 // http://crbug.com/591504.
511 if (!RecursiveDirectoryCreate(*crash_dir)) 543 if (!RecursiveDirectoryCreate(crash_dir->c_str()))
512 return false; 544 return false;
513 crash_dir->append(L"\\Crashpad"); 545 crash_dir->append(L"\\Crashpad");
514 return true; 546 return true;
515 } 547 }
516 548
517 std::string GetEnvironmentString(const std::string& variable_name) { 549 std::string GetEnvironmentString(const std::string& variable_name) {
518 return UTF16ToUTF8( 550 return UTF16ToUTF8(GetEnvironmentString16(UTF8ToUTF16(variable_name)));
519 GetEnvironmentString16(UTF8ToUTF16(variable_name).c_str()));
520 } 551 }
521 552
522 std::wstring GetEnvironmentString16(const wchar_t* variable_name) { 553 std::wstring GetEnvironmentString16(const std::wstring& variable_name) {
523 DWORD value_length = ::GetEnvironmentVariableW(variable_name, nullptr, 0); 554 DWORD value_length =
524 if (!value_length) 555 ::GetEnvironmentVariable(variable_name.c_str(), nullptr, 0);
556 if (value_length == 0)
525 return std::wstring(); 557 return std::wstring();
526 std::wstring value(value_length, L'\0'); 558 std::unique_ptr<wchar_t[]> value(new wchar_t[value_length]);
527 value_length = 559 ::GetEnvironmentVariable(variable_name.c_str(), value.get(), value_length);
528 ::GetEnvironmentVariableW(variable_name, &value[0], value_length); 560 return value.get();
529 if (!value_length || value_length >= value.size())
530 return std::wstring();
531 value.resize(value_length);
532 return value;
533 } 561 }
534 562
535 bool SetEnvironmentString(const std::string& variable_name, 563 bool SetEnvironmentString(const std::string& variable_name,
536 const std::string& new_value) { 564 const std::string& new_value) {
537 return SetEnvironmentString16(UTF8ToUTF16(variable_name), 565 return SetEnvironmentString16(UTF8ToUTF16(variable_name),
538 UTF8ToUTF16(new_value)); 566 UTF8ToUTF16(new_value));
539 } 567 }
540 568
541 bool SetEnvironmentString16(const std::wstring& variable_name, 569 bool SetEnvironmentString16(const std::wstring& variable_name,
542 const std::wstring& new_value) { 570 const std::wstring& new_value) {
543 return !!SetEnvironmentVariable(variable_name.c_str(), new_value.c_str()); 571 return !!SetEnvironmentVariable(variable_name.c_str(), new_value.c_str());
544 } 572 }
545 573
546 bool HasEnvironmentVariable(const std::string& variable_name) { 574 bool HasEnvironmentVariable(const std::string& variable_name) {
547 return HasEnvironmentVariable16(UTF8ToUTF16(variable_name)); 575 return HasEnvironmentVariable16(UTF8ToUTF16(variable_name));
548 } 576 }
549 577
550 bool HasEnvironmentVariable16(const std::wstring& variable_name) { 578 bool HasEnvironmentVariable16(const std::wstring& variable_name) {
551 return !!::GetEnvironmentVariable(variable_name.c_str(), nullptr, 0); 579 return !!::GetEnvironmentVariable(variable_name.c_str(), nullptr, 0);
552 } 580 }
553 581
554 void GetExecutableVersionDetails(const std::wstring& exe_path, 582 bool GetExecutableVersionDetails(const std::wstring& exe_path,
555 std::wstring* product_name, 583 std::wstring* product_name,
556 std::wstring* version, 584 std::wstring* version,
557 std::wstring* special_build, 585 std::wstring* special_build,
558 std::wstring* channel_name) { 586 std::wstring* channel_name) {
559 assert(product_name); 587 assert(product_name);
560 assert(version); 588 assert(version);
561 assert(special_build); 589 assert(special_build);
562 assert(channel_name); 590 assert(channel_name);
563 591
564 // Default values in case we don't find a version resource. 592 // Default values in case we don't find a version resource.
565 *product_name = L"Chrome"; 593 *product_name = L"Chrome";
566 *version = L"0.0.0.0-devel"; 594 *version = L"0.0.0.0-devel";
595 *channel_name = kChromeChannelUnknown;
567 special_build->clear(); 596 special_build->clear();
568 597
569 DWORD dummy = 0; 598 DWORD dummy = 0;
570 DWORD length = ::GetFileVersionInfoSize(exe_path.c_str(), &dummy); 599 DWORD length = ::GetFileVersionInfoSize(exe_path.c_str(), &dummy);
571 if (length) { 600 if (length) {
572 std::unique_ptr<char> data(new char[length]); 601 std::unique_ptr<char> data(new char[length]);
573 if (::GetFileVersionInfo(exe_path.c_str(), dummy, length, data.get())) { 602 if (::GetFileVersionInfo(exe_path.c_str(), dummy, length, data.get())) {
574 GetValueFromVersionResource(data.get(), L"ProductVersion", version); 603 GetValueFromVersionResource(data.get(), L"ProductVersion", version);
575 604
576 std::wstring official_build; 605 std::wstring official_build;
577 GetValueFromVersionResource(data.get(), L"Official Build", 606 GetValueFromVersionResource(data.get(), L"Official Build",
578 &official_build); 607 &official_build);
579 if (official_build != L"1") 608 if (official_build != L"1")
580 version->append(L"-devel"); 609 version->append(L"-devel");
581 GetValueFromVersionResource(data.get(), L"ProductShortName", 610 GetValueFromVersionResource(data.get(), L"ProductShortName",
582 product_name); 611 product_name);
583 GetValueFromVersionResource(data.get(), L"SpecialBuild", special_build); 612 GetValueFromVersionResource(data.get(), L"SpecialBuild", special_build);
584 } 613 }
585 } 614 }
586 *channel_name = GetChromeChannelName(true /* add_modifier */); 615 GetChromeChannelName(!IsSystemInstall(exe_path.c_str()), true, channel_name);
616 return true;
587 } 617 }
588 618
589 std::wstring GetChromeChannelName(bool add_modifier) { 619 void GetChromeChannelName(bool is_per_user_install,
590 const std::wstring& channel = InstallDetails::Get().channel(); 620 bool add_modifier,
591 if (!add_modifier || !IsMultiInstall()) 621 std::wstring* channel_name) {
592 return channel; 622 // See GoogleChromeSxSDistribution::GetChromeChannel.
593 if (channel.empty()) 623 if (IsSxSChrome(GetCurrentProcessExePath().c_str())) {
594 return L"m"; 624 channel_name->assign(kChromeChannelCanary);
595 return channel + L"-m"; 625 return;
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
596 } 710 }
597 711
598 std::wstring GetBrowserCrashDumpAttemptsRegistryPath() { 712 std::wstring GetBrowserCrashDumpAttemptsRegistryPath() {
599 return GetChromeInstallRegistryPath().append(kBrowserCrashDumpMetricsSubKey); 713 std::wstring registry_path = GetChromeInstallRegistryPath();
714 registry_path += kBrowserCrashDumpMetricsSubKey;
715 return registry_path;
600 } 716 }
601 717
602 bool MatchPattern(const std::wstring& source, const std::wstring& pattern) { 718 bool MatchPattern(const std::wstring& source, const std::wstring& pattern) {
603 assert(pattern.find(L"**") == std::wstring::npos); 719 assert(pattern.find(L"**") == std::wstring::npos);
604 return MatchPatternImpl(source, pattern, 0, 0); 720 return MatchPatternImpl(source, pattern, 0, 0);
605 } 721 }
606 722
607 std::string UTF16ToUTF8(const std::wstring& source) { 723 std::string UTF16ToUTF8(const std::wstring& source) {
608 if (source.empty() || 724 if (source.empty() ||
609 static_cast<int>(source.size()) > std::numeric_limits<int>::max()) { 725 static_cast<int>(source.size()) > std::numeric_limits<int>::max()) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 bool trim_spaces) { 760 bool trim_spaces) {
645 return TokenizeStringT<std::string>(str, delimiter, trim_spaces); 761 return TokenizeStringT<std::string>(str, delimiter, trim_spaces);
646 } 762 }
647 763
648 std::vector<std::wstring> TokenizeString16(const std::wstring& str, 764 std::vector<std::wstring> TokenizeString16(const std::wstring& str,
649 wchar_t delimiter, 765 wchar_t delimiter,
650 bool trim_spaces) { 766 bool trim_spaces) {
651 return TokenizeStringT<std::wstring>(str, delimiter, trim_spaces); 767 return TokenizeStringT<std::wstring>(str, delimiter, trim_spaces);
652 } 768 }
653 769
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
654 std::string GetSwitchValueFromCommandLine(const std::string& command_line, 847 std::string GetSwitchValueFromCommandLine(const std::string& command_line,
655 const std::string& switch_name) { 848 const std::string& switch_name) {
656 assert(!command_line.empty()); 849 assert(!command_line.empty());
657 assert(!switch_name.empty()); 850 assert(!switch_name.empty());
658 851
659 std::string command_line_copy = command_line; 852 std::string command_line_copy = command_line;
660 // Remove leading and trailing spaces. 853 // Remove leading and trailing spaces.
661 TrimT<std::string>(&command_line_copy); 854 TrimT<std::string>(&command_line_copy);
662 855
663 // Find the switch in the command line. If we don't find the switch, return 856 // Find the switch in the command line. If we don't find the switch, return
(...skipping 22 matching lines...) Expand all
686 if (switch_value_end_offset == std::string::npos) 879 if (switch_value_end_offset == std::string::npos)
687 switch_value_end_offset = command_line_copy.length(); 880 switch_value_end_offset = command_line_copy.length();
688 881
689 std::string switch_value = command_line_copy.substr( 882 std::string switch_value = command_line_copy.substr(
690 switch_value_start_offset, 883 switch_value_start_offset,
691 switch_value_end_offset - (switch_offset + switch_token.length())); 884 switch_value_end_offset - (switch_offset + switch_token.length()));
692 TrimT<std::string>(&switch_value); 885 TrimT<std::string>(&switch_value);
693 return switch_value; 886 return switch_value;
694 } 887 }
695 888
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
717 } // namespace install_static 889 } // namespace install_static
OLDNEW
« no previous file with comments | « chrome/install_static/install_util.h ('k') | chrome/install_static/install_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698