Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 <algorithm> | 9 #include <algorithm> |
| 10 #include <iostream> | |
| 11 #include <iterator> | |
| 10 #include <memory> | 12 #include <memory> |
| 13 #include <sstream> | |
| 11 | 14 |
| 12 #include "base/macros.h" | 15 #include "base/macros.h" |
| 13 #include "build/build_config.h" | 16 #include "build/build_config.h" |
| 14 | 17 |
| 15 namespace install_static { | 18 namespace install_static { |
| 16 | 19 |
| 17 ProcessType g_process_type = ProcessType::UNINITIALIZED; | 20 ProcessType g_process_type = ProcessType::UNINITIALIZED; |
| 18 | 21 |
| 19 // TODO(ananta) | 22 // TODO(ananta) |
| 20 // http://crbug.com/604923 | 23 // http://crbug.com/604923 |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 248 } | 251 } |
| 249 | 252 |
| 250 // Returns the executable path for the current process. | 253 // Returns the executable path for the current process. |
| 251 base::string16 GetCurrentProcessExePath() { | 254 base::string16 GetCurrentProcessExePath() { |
| 252 wchar_t exe_path[MAX_PATH]; | 255 wchar_t exe_path[MAX_PATH]; |
| 253 if (GetModuleFileName(nullptr, exe_path, arraysize(exe_path)) == 0) | 256 if (GetModuleFileName(nullptr, exe_path, arraysize(exe_path)) == 0) |
| 254 return base::string16(); | 257 return base::string16(); |
| 255 return exe_path; | 258 return exe_path; |
| 256 } | 259 } |
| 257 | 260 |
| 258 // UTF8 to UTF16 and vice versa conversion helpers. We cannot use the base | |
| 259 // string conversion utilities here as they bring about a dependency on | |
| 260 // user32.dll which is not allowed in this file. | |
| 261 | |
| 262 // Convert a UTF16 string to an UTF8 string. | |
| 263 std::string utf16_to_utf8(const base::string16 &source) { | |
| 264 if (source.empty()) | |
| 265 return std::string(); | |
| 266 int size = ::WideCharToMultiByte(CP_UTF8, 0, &source[0], | |
| 267 static_cast<int>(source.size()), nullptr, 0, nullptr, nullptr); | |
| 268 std::string result(size, '\0'); | |
| 269 if (::WideCharToMultiByte(CP_UTF8, 0, &source[0], | |
| 270 static_cast<int>(source.size()), &result[0], size, nullptr, | |
| 271 nullptr) != size) { | |
| 272 assert(false); | |
| 273 return std::string(); | |
| 274 } | |
| 275 return result; | |
| 276 } | |
| 277 | |
| 278 // Convert a UTF8 string to a UTF16 string. | |
| 279 base::string16 utf8_to_string16(const std::string &source) { | |
| 280 if (source.empty()) | |
| 281 return base::string16(); | |
| 282 int size = ::MultiByteToWideChar(CP_UTF8, 0, &source[0], | |
| 283 static_cast<int>(source.size()), nullptr, 0); | |
| 284 base::string16 result(size, L'\0'); | |
| 285 if (::MultiByteToWideChar(CP_UTF8, 0, &source[0], | |
| 286 static_cast<int>(source.size()), &result[0], size) != size) { | |
| 287 assert(false); | |
| 288 return base::string16(); | |
| 289 } | |
| 290 return result; | |
| 291 } | |
| 292 | |
| 293 bool RecursiveDirectoryCreate(const base::string16& full_path) { | 261 bool RecursiveDirectoryCreate(const base::string16& full_path) { |
| 294 // If the path exists, we've succeeded if it's a directory, failed otherwise. | 262 // If the path exists, we've succeeded if it's a directory, failed otherwise. |
| 295 const wchar_t* full_path_str = full_path.c_str(); | 263 const wchar_t* full_path_str = full_path.c_str(); |
| 296 DWORD file_attributes = ::GetFileAttributes(full_path_str); | 264 DWORD file_attributes = ::GetFileAttributes(full_path_str); |
| 297 if (file_attributes != INVALID_FILE_ATTRIBUTES) { | 265 if (file_attributes != INVALID_FILE_ATTRIBUTES) { |
| 298 if ((file_attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { | 266 if ((file_attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { |
| 299 Trace(L"%hs( %ls directory exists )\n", __FUNCTION__, full_path_str); | 267 Trace(L"%hs( %ls directory exists )\n", __FUNCTION__, full_path_str); |
| 300 return true; | 268 return true; |
| 301 } | 269 } |
| 302 Trace(L"%hs( %ls directory conflicts with an existing file. )\n", | 270 Trace(L"%hs( %ls directory conflicts with an existing file. )\n", |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 412 // 1. We consider current character of source. | 380 // 1. We consider current character of source. |
| 413 // 2. We ignore current character of source. | 381 // 2. We ignore current character of source. |
| 414 if (pattern[pattern_index] == L'*') { | 382 if (pattern[pattern_index] == L'*') { |
| 415 return MatchPatternImpl(source, pattern, source_index + 1, | 383 return MatchPatternImpl(source, pattern, source_index + 1, |
| 416 pattern_index) || | 384 pattern_index) || |
| 417 MatchPatternImpl(source, pattern, source_index, pattern_index + 1); | 385 MatchPatternImpl(source, pattern, source_index, pattern_index + 1); |
| 418 } | 386 } |
| 419 return false; | 387 return false; |
| 420 } | 388 } |
| 421 | 389 |
| 390 // Defines the type of whitespace characters typically found in strings. | |
| 391 const char kWhiteSpaces[] = " \t\n\r\f\v"; | |
|
grt (UTC plus 2)
2016/05/27 14:13:20
nit: constexpr
ananta
2016/05/27 20:05:25
Done.
| |
| 392 | |
| 393 // Trim whitespaces from left. | |
| 394 void ltrim(std::string* str) { | |
| 395 str->erase(0, str->find_first_not_of(kWhiteSpaces)); | |
| 396 } | |
| 397 | |
| 398 // Trim whitespaces from right | |
| 399 void rtrim(std::string* str) { | |
| 400 str->erase(str->find_last_not_of(kWhiteSpaces) + 1); | |
| 401 } | |
| 402 | |
| 403 // Trim whitespaces from left & right | |
| 404 void trim(std::string* str) { | |
|
scottmg
2016/05/27 17:27:22
trim -> Trim
ananta
2016/05/27 20:05:25
Done.
| |
| 405 rtrim(str); | |
|
scottmg
2016/05/27 17:27:22
Seems like over-functioning since ltrim() and rtri
ananta
2016/05/27 20:05:25
Done.
| |
| 406 ltrim(str); | |
| 407 } | |
| 408 | |
| 409 bool is_valid_number(const std::string &str) { | |
|
scottmg
2016/05/27 17:27:22
IsValidNumber
ananta
2016/05/27 20:05:25
Done.
| |
| 410 return std::all_of(str.begin(), str.end(), ::isdigit); | |
|
grt (UTC plus 2)
2016/05/27 14:13:20
as implemented, this will return true if std.empty
ananta
2016/05/27 20:05:25
Done.
| |
| 411 } | |
| 412 | |
| 422 } // namespace | 413 } // namespace |
| 423 | 414 |
| 424 bool IsSxSChrome(const wchar_t* exe_path) { | 415 bool IsSxSChrome(const wchar_t* exe_path) { |
| 425 return wcsstr(exe_path, L"Chrome SxS\\Application") != NULL; | 416 return wcsstr(exe_path, L"Chrome SxS\\Application") != NULL; |
| 426 } | 417 } |
| 427 | 418 |
| 428 bool IsSystemInstall(const wchar_t* exe_path) { | 419 bool IsSystemInstall(const wchar_t* exe_path) { |
| 429 wchar_t program_dir[MAX_PATH] = {}; | 420 wchar_t program_dir[MAX_PATH] = {}; |
| 430 DWORD ret = ::GetEnvironmentVariable(L"PROGRAMFILES", program_dir, | 421 DWORD ret = ::GetEnvironmentVariable(L"PROGRAMFILES", program_dir, |
| 431 arraysize(program_dir)); | 422 arraysize(program_dir)); |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 569 // http://crbug.com/591504. | 560 // http://crbug.com/591504. |
| 570 if (!RecursiveDirectoryCreate(crash_dir->c_str())) | 561 if (!RecursiveDirectoryCreate(crash_dir->c_str())) |
| 571 return false; | 562 return false; |
| 572 crash_dir->append(L"\\Crashpad"); | 563 crash_dir->append(L"\\Crashpad"); |
| 573 return true; | 564 return true; |
| 574 } | 565 } |
| 575 | 566 |
| 576 | 567 |
| 577 std::string GetEnvironmentString(const std::string& variable_name) { | 568 std::string GetEnvironmentString(const std::string& variable_name) { |
| 578 DWORD value_length = ::GetEnvironmentVariable( | 569 DWORD value_length = ::GetEnvironmentVariable( |
| 579 utf8_to_string16(variable_name).c_str(), NULL, 0); | 570 utf8_to_utf16(variable_name).c_str(), NULL, 0); |
| 580 if (value_length == 0) | 571 if (value_length == 0) |
| 581 return std::string(); | 572 return std::string(); |
| 582 std::unique_ptr<wchar_t[]> value(new wchar_t[value_length]); | 573 std::unique_ptr<wchar_t[]> value(new wchar_t[value_length]); |
| 583 ::GetEnvironmentVariable(utf8_to_string16(variable_name).c_str(), | 574 ::GetEnvironmentVariable(utf8_to_utf16(variable_name).c_str(), |
| 584 value.get(), value_length); | 575 value.get(), value_length); |
| 585 return utf16_to_utf8(value.get()); | 576 return utf16_to_utf8(value.get()); |
| 586 } | 577 } |
| 587 | 578 |
| 588 bool SetEnvironmentString(const std::string& variable_name, | 579 bool SetEnvironmentString(const std::string& variable_name, |
| 589 const std::string& new_value) { | 580 const std::string& new_value) { |
| 590 return !!SetEnvironmentVariable(utf8_to_string16(variable_name).c_str(), | 581 return !!SetEnvironmentVariable(utf8_to_utf16(variable_name).c_str(), |
| 591 utf8_to_string16(new_value).c_str()); | 582 utf8_to_utf16(new_value).c_str()); |
| 592 } | 583 } |
| 593 | 584 |
| 594 bool HasEnvironmentVariable(const std::string& variable_name) { | 585 bool HasEnvironmentVariable(const std::string& variable_name) { |
| 595 return !!::GetEnvironmentVariable(utf8_to_string16(variable_name).c_str(), | 586 return !!::GetEnvironmentVariable(utf8_to_utf16(variable_name).c_str(), |
| 596 NULL, 0); | 587 NULL, 0); |
| 597 } | 588 } |
| 598 | 589 |
| 599 bool GetExecutableVersionDetails(const base::string16& exe_path, | 590 bool GetExecutableVersionDetails(const base::string16& exe_path, |
| 600 base::string16* product_name, | 591 base::string16* product_name, |
| 601 base::string16* version, | 592 base::string16* version, |
| 602 base::string16* special_build, | 593 base::string16* special_build, |
| 603 base::string16* channel_name) { | 594 base::string16* channel_name) { |
| 604 assert(product_name); | 595 assert(product_name); |
| 605 assert(version); | 596 assert(version); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 736 registry_path += kBrowserCrashDumpMetricsSubKey; | 727 registry_path += kBrowserCrashDumpMetricsSubKey; |
| 737 return registry_path; | 728 return registry_path; |
| 738 } | 729 } |
| 739 | 730 |
| 740 bool MatchPattern(const base::string16& source, | 731 bool MatchPattern(const base::string16& source, |
| 741 const base::string16& pattern) { | 732 const base::string16& pattern) { |
| 742 assert(pattern.find(L"**") == base::string16::npos); | 733 assert(pattern.find(L"**") == base::string16::npos); |
| 743 return MatchPatternImpl(source, pattern, 0, 0); | 734 return MatchPatternImpl(source, pattern, 0, 0); |
| 744 } | 735 } |
| 745 | 736 |
| 737 std::string utf16_to_utf8(const base::string16 &source) { | |
|
grt (UTC plus 2)
2016/05/27 14:13:20
nit: & before space. please use "git cl format" t
ananta
2016/05/27 20:05:25
Yeah. I had done that. It seems every time I copy
| |
| 738 if (source.empty()) | |
|
grt (UTC plus 2)
2016/05/27 14:13:20
|| source.size() > std::numeric_limits<int>::max()
ananta
2016/05/27 20:05:25
Done.
| |
| 739 return std::string(); | |
| 740 int size = ::WideCharToMultiByte(CP_UTF8, 0, &source[0], | |
| 741 static_cast<int>(source.size()), nullptr, 0, nullptr, nullptr); | |
| 742 std::string result(size, '\0'); | |
| 743 if (::WideCharToMultiByte(CP_UTF8, 0, &source[0], | |
| 744 static_cast<int>(source.size()), &result[0], size, nullptr, | |
| 745 nullptr) != size) { | |
| 746 assert(false); | |
| 747 return std::string(); | |
| 748 } | |
| 749 return result; | |
| 750 } | |
| 751 | |
| 752 base::string16 utf8_to_utf16(const std::string &source) { | |
| 753 if (source.empty()) | |
|
grt (UTC plus 2)
2016/05/27 14:13:20
|| source.size() > std::numeric_limits<int>::max()
ananta
2016/05/27 20:05:25
Done.
| |
| 754 return base::string16(); | |
| 755 int size = ::MultiByteToWideChar(CP_UTF8, 0, &source[0], | |
| 756 static_cast<int>(source.size()), nullptr, 0); | |
| 757 base::string16 result(size, L'\0'); | |
| 758 if (::MultiByteToWideChar(CP_UTF8, 0, &source[0], | |
| 759 static_cast<int>(source.size()), &result[0], size) != size) { | |
| 760 assert(false); | |
| 761 return base::string16(); | |
| 762 } | |
| 763 return result; | |
| 764 } | |
| 765 | |
| 766 std::vector<std::string> TokenizeString(const std::string& str, | |
| 767 const char delimiter, | |
|
grt (UTC plus 2)
2016/05/27 14:13:20
no const
ananta
2016/05/27 20:05:25
Done.
| |
| 768 bool trim_spaces) { | |
|
scottmg
2016/05/27 17:27:22
I only see trim_spaces=false calls other than in t
ananta
2016/05/27 20:05:25
Prefer to leave it as an argument. Just in case we
| |
| 769 std::vector<std::string> tokens; | |
| 770 std::istringstream buffer(str); | |
| 771 for (std::string token; std::getline(buffer, token, delimiter); ) { | |
| 772 if (trim_spaces) | |
| 773 trim(&token); | |
| 774 tokens.push_back(token); | |
| 775 } | |
| 776 return tokens; | |
| 777 } | |
| 778 | |
| 779 bool CompareVersionStrings(const std::string& version1, | |
| 780 const std::string& version2, | |
| 781 int* result) { | |
| 782 if (version1.empty() || version2.empty()) | |
| 783 return false; | |
| 784 | |
| 785 // Tokenize both version strings with "." as the separator. If either of | |
| 786 // the returned token lists are empty then bail. | |
| 787 std::vector<std::string> version1_components = | |
| 788 install_static::TokenizeString(version1, '.', false); | |
|
grt (UTC plus 2)
2016/05/27 14:13:20
omit "install_static::"
ananta
2016/05/27 20:05:25
Done.
| |
| 789 if (version1_components.empty()) | |
| 790 return false; | |
| 791 | |
| 792 std::vector<std::string> version2_components = | |
| 793 install_static::TokenizeString(version2, '.', false); | |
| 794 if (version2_components.empty()) | |
| 795 return false; | |
| 796 | |
| 797 // You may have less tokens in either string. Use the minimum of the number | |
| 798 // of tokens as the initial count. | |
| 799 const size_t count = std::min(version1_components.size(), | |
|
scottmg
2016/05/27 17:27:22
nit; weird line break
ananta
2016/05/27 20:05:25
Done.
| |
| 800 version2_components.size()); | |
| 801 for (size_t i = 0; i < count; ++i) { | |
| 802 // If either of the version components don't contain valid numeric digits | |
| 803 // bail. | |
| 804 if (!is_valid_number(version1_components[i]) || | |
| 805 !is_valid_number(version2_components[i])) { | |
| 806 return false; | |
| 807 } | |
| 808 | |
| 809 int version1_component = std::stoi(version1_components[i]); | |
|
scottmg
2016/05/27 17:27:22
Ooh, this defaults to base=10, not =0, woohoo!
ananta
2016/05/27 20:05:25
Yeah
| |
| 810 int version2_component = std::stoi(version2_components[i]); | |
| 811 | |
| 812 if (version1_component > version2_component) { | |
| 813 *result = 1; | |
| 814 return true; | |
| 815 } | |
| 816 | |
| 817 if (version1_component < version2_component) { | |
| 818 *result = -1; | |
| 819 return true; | |
| 820 } | |
| 821 } | |
| 822 | |
| 823 // Handle remaining tokens. Here if we have non zero tokens remaining in the | |
| 824 // version 1 list then it means that the version1 string is larger. If the | |
| 825 // version 1 token list has tokens left, then if either of these tokens is | |
| 826 // greater than 0 then it means that the version1 string is smaller than the | |
| 827 // version2 string. | |
| 828 if (version1_components.size() > version2_components.size()) { | |
| 829 for (size_t i = count; i < version1_components.size(); ++i) { | |
| 830 // If the version components don't contain valid numeric digits bail. | |
| 831 if (!is_valid_number(version1_components[i])) | |
| 832 return false; | |
| 833 | |
| 834 if (std::stoi(version1_components[i]) > 0) { | |
| 835 *result = 1; | |
| 836 return true; | |
| 837 } | |
| 838 } | |
| 839 } else if (version1_components.size() < version2_components.size()) { | |
| 840 for (size_t i = count; i < version2_components.size(); ++i) { | |
| 841 // If the version components don't contain valid numeric digits bail. | |
| 842 if (!is_valid_number(version2_components[i])) | |
| 843 return false; | |
| 844 | |
| 845 if (std::stoi(version2_components[i]) > 0) { | |
| 846 *result = -1; | |
| 847 return true; | |
| 848 } | |
| 849 } | |
| 850 } | |
| 851 // Here it means that both versions are equal. | |
| 852 *result = 0; | |
| 853 return true; | |
| 854 } | |
| 855 | |
| 746 } // namespace install_static | 856 } // namespace install_static |
| OLD | NEW |