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

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

Issue 2017853002: Add functionality to the install_static library to tokenize strings and compare versions. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update comment Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« 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 <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
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
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 constexpr char kWhiteSpaces[] = " \t\n\r\f\v";
392
393 // Trim whitespaces from left & right
394 void Trim(std::string* str) {
395 str->erase(str->find_last_not_of(kWhiteSpaces) + 1);
396 str->erase(0, str->find_first_not_of(kWhiteSpaces));
397 }
398
399 bool IsValidNumber(const std::string& str) {
400 if (str.empty())
401 return false;
402 return std::all_of(str.begin(), str.end(), ::isdigit);
403 }
404
422 } // namespace 405 } // namespace
423 406
424 bool IsSxSChrome(const wchar_t* exe_path) { 407 bool IsSxSChrome(const wchar_t* exe_path) {
425 return wcsstr(exe_path, L"Chrome SxS\\Application") != NULL; 408 return wcsstr(exe_path, L"Chrome SxS\\Application") != NULL;
426 } 409 }
427 410
428 bool IsSystemInstall(const wchar_t* exe_path) { 411 bool IsSystemInstall(const wchar_t* exe_path) {
429 wchar_t program_dir[MAX_PATH] = {}; 412 wchar_t program_dir[MAX_PATH] = {};
430 DWORD ret = ::GetEnvironmentVariable(L"PROGRAMFILES", program_dir, 413 DWORD ret = ::GetEnvironmentVariable(L"PROGRAMFILES", program_dir,
431 arraysize(program_dir)); 414 arraysize(program_dir));
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 // We have to make sure the user data dir exists on first run. See 551 // We have to make sure the user data dir exists on first run. See
569 // http://crbug.com/591504. 552 // http://crbug.com/591504.
570 if (!RecursiveDirectoryCreate(crash_dir->c_str())) 553 if (!RecursiveDirectoryCreate(crash_dir->c_str()))
571 return false; 554 return false;
572 crash_dir->append(L"\\Crashpad"); 555 crash_dir->append(L"\\Crashpad");
573 return true; 556 return true;
574 } 557 }
575 558
576 559
577 std::string GetEnvironmentString(const std::string& variable_name) { 560 std::string GetEnvironmentString(const std::string& variable_name) {
578 DWORD value_length = ::GetEnvironmentVariable( 561 DWORD value_length =
579 utf8_to_string16(variable_name).c_str(), NULL, 0); 562 ::GetEnvironmentVariable(UTF8ToUTF16(variable_name).c_str(), NULL, 0);
grt (UTC plus 2) 2016/05/27 20:18:04 nullptr everywhere
ananta 2016/05/27 20:42:13 Done.
580 if (value_length == 0) 563 if (value_length == 0)
581 return std::string(); 564 return std::string();
582 std::unique_ptr<wchar_t[]> value(new wchar_t[value_length]); 565 std::unique_ptr<wchar_t[]> value(new wchar_t[value_length]);
583 ::GetEnvironmentVariable(utf8_to_string16(variable_name).c_str(), 566 ::GetEnvironmentVariable(UTF8ToUTF16(variable_name).c_str(), value.get(),
584 value.get(), value_length); 567 value_length);
585 return utf16_to_utf8(value.get()); 568 return UTF16ToUTF8(value.get());
586 } 569 }
587 570
588 bool SetEnvironmentString(const std::string& variable_name, 571 bool SetEnvironmentString(const std::string& variable_name,
589 const std::string& new_value) { 572 const std::string& new_value) {
590 return !!SetEnvironmentVariable(utf8_to_string16(variable_name).c_str(), 573 return !!SetEnvironmentVariable(UTF8ToUTF16(variable_name).c_str(),
591 utf8_to_string16(new_value).c_str()); 574 UTF8ToUTF16(new_value).c_str());
592 } 575 }
593 576
594 bool HasEnvironmentVariable(const std::string& variable_name) { 577 bool HasEnvironmentVariable(const std::string& variable_name) {
595 return !!::GetEnvironmentVariable(utf8_to_string16(variable_name).c_str(), 578 return !!::GetEnvironmentVariable(UTF8ToUTF16(variable_name).c_str(), NULL,
596 NULL, 0); 579 0);
597 } 580 }
598 581
599 bool GetExecutableVersionDetails(const base::string16& exe_path, 582 bool GetExecutableVersionDetails(const base::string16& exe_path,
600 base::string16* product_name, 583 base::string16* product_name,
601 base::string16* version, 584 base::string16* version,
602 base::string16* special_build, 585 base::string16* special_build,
603 base::string16* channel_name) { 586 base::string16* channel_name) {
604 assert(product_name); 587 assert(product_name);
605 assert(version); 588 assert(version);
606 assert(special_build); 589 assert(special_build);
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
705 std::string GetGoogleUpdateVersion() { 688 std::string GetGoogleUpdateVersion() {
706 // TODO(ananta) 689 // TODO(ananta)
707 // Consider whether Chromium should connect to Google update to manage 690 // Consider whether Chromium should connect to Google update to manage
708 // updates. Should this be returning an empty string for Chromium builds?. 691 // updates. Should this be returning an empty string for Chromium builds?.
709 base::string16 update_version; 692 base::string16 update_version;
710 if (ReadKeyValueString(IsSystemInstall(GetCurrentProcessExePath().c_str()), 693 if (ReadKeyValueString(IsSystemInstall(GetCurrentProcessExePath().c_str()),
711 kRegPathGoogleUpdate, 694 kRegPathGoogleUpdate,
712 nullptr, 695 nullptr,
713 kRegGoogleUpdateVersion, 696 kRegGoogleUpdateVersion,
714 &update_version)) { 697 &update_version)) {
715 return utf16_to_utf8(update_version); 698 return UTF16ToUTF8(update_version);
716 } 699 }
717 return std::string(); 700 return std::string();
718 } 701 }
719 702
720 base::string16 GetChromeInstallSubDirectory() { 703 base::string16 GetChromeInstallSubDirectory() {
721 #if defined(GOOGLE_CHROME_BUILD) 704 #if defined(GOOGLE_CHROME_BUILD)
722 base::string16 result = kGoogleChromeInstallSubDir1; 705 base::string16 result = kGoogleChromeInstallSubDir1;
723 result += L"\\"; 706 result += L"\\";
724 result += kGoogleChromeInstallSubDir2; 707 result += kGoogleChromeInstallSubDir2;
725 if (IsSxSChrome(GetCurrentProcessExePath().c_str())) 708 if (IsSxSChrome(GetCurrentProcessExePath().c_str()))
(...skipping 10 matching lines...) Expand all
736 registry_path += kBrowserCrashDumpMetricsSubKey; 719 registry_path += kBrowserCrashDumpMetricsSubKey;
737 return registry_path; 720 return registry_path;
738 } 721 }
739 722
740 bool MatchPattern(const base::string16& source, 723 bool MatchPattern(const base::string16& source,
741 const base::string16& pattern) { 724 const base::string16& pattern) {
742 assert(pattern.find(L"**") == base::string16::npos); 725 assert(pattern.find(L"**") == base::string16::npos);
743 return MatchPatternImpl(source, pattern, 0, 0); 726 return MatchPatternImpl(source, pattern, 0, 0);
744 } 727 }
745 728
729 std::string UTF16ToUTF8(const base::string16& source) {
730 if (source.empty() ||
731 static_cast<int>(source.size()) > std::numeric_limits<int>::max()) {
732 return std::string();
733 }
734 int size = ::WideCharToMultiByte(CP_UTF8, 0, &source[0],
735 static_cast<int>(source.size()), nullptr, 0,
736 nullptr, nullptr);
737 std::string result(size, '\0');
738 if (::WideCharToMultiByte(CP_UTF8, 0, &source[0],
739 static_cast<int>(source.size()), &result[0], size,
740 nullptr, nullptr) != size) {
741 assert(false);
742 return std::string();
743 }
744 return result;
745 }
746
747 base::string16 UTF8ToUTF16(const std::string& source) {
748 if (source.empty() ||
749 static_cast<int>(source.size()) > std::numeric_limits<int>::max()) {
750 return base::string16();
751 }
752 int size = ::MultiByteToWideChar(CP_UTF8, 0, &source[0],
753 static_cast<int>(source.size()), nullptr, 0);
754 base::string16 result(size, L'\0');
755 if (::MultiByteToWideChar(CP_UTF8, 0, &source[0],
756 static_cast<int>(source.size()), &result[0],
757 size) != size) {
758 assert(false);
759 return base::string16();
760 }
761 return result;
762 }
763
764 std::vector<std::string> TokenizeString(const std::string& str,
765 char delimiter,
766 bool trim_spaces) {
767 std::vector<std::string> tokens;
768 std::istringstream buffer(str);
769 for (std::string token; std::getline(buffer, token, delimiter);) {
770 if (trim_spaces)
771 Trim(&token);
772 tokens.push_back(token);
773 }
774 return tokens;
775 }
776
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
746 } // namespace install_static 854 } // 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