| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/installer/setup/update_active_setup_version_work_item.h" |
| |
| #include <stdint.h> |
| |
| #include <algorithm> |
| #include <vector> |
| |
| #include "base/bind.h" |
| #include "base/logging.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_split.h" |
| #include "base/strings/string_util.h" |
| |
| namespace { |
| |
| // The major version and first component of the version identifying the work |
| // done by setup.exe --configure-user-settings on user login by way of Active |
| // Setup. Increase this value if the work done when handling Active Setup |
| // should be executed again for all existing users. |
| #define ACTIVE_SETUP_MAJOR_VERSION 43 |
| |
| #define AsChar16String2(m) L#m |
| #define AsChar16String(m) AsChar16String2(m) |
| |
| constexpr base::char16 kActiveSetupMajorVersion[] = |
| AsChar16String(ACTIVE_SETUP_MAJOR_VERSION); |
| |
| #undef AsChar16String |
| #undef AsChar16String2 |
| |
| } // namespace |
| |
| UpdateActiveSetupVersionWorkItem::UpdateActiveSetupVersionWorkItem( |
| const base::string16& active_setup_path, |
| Operation operation) |
| : set_reg_value_work_item_( |
| HKEY_LOCAL_MACHINE, |
| active_setup_path, |
| WorkItem::kWow64Default, |
| L"Version", |
| base::Bind( |
| &UpdateActiveSetupVersionWorkItem::GetUpdatedActiveSetupVersion, |
| base::Unretained(this))), |
| operation_(operation) { |
| } |
| |
| bool UpdateActiveSetupVersionWorkItem::DoImpl() { |
| set_reg_value_work_item_.set_best_effort(best_effort()); |
| set_reg_value_work_item_.set_rollback_enabled(rollback_enabled()); |
| return set_reg_value_work_item_.Do(); |
| } |
| |
| void UpdateActiveSetupVersionWorkItem::RollbackImpl() { |
| set_reg_value_work_item_.Rollback(); |
| } |
| |
| base::string16 UpdateActiveSetupVersionWorkItem::GetUpdatedActiveSetupVersion( |
| const base::string16& existing_version) { |
| std::vector<base::string16> version_components = base::SplitString( |
| existing_version, L",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| |
| // If |existing_version| was empty or otherwise corrupted, turn it into a |
| // valid one by extending with up to four zeros or truncating to only four |
| // components. |
| if (version_components.size() != 4U) |
| version_components.resize(4U, L"0"); |
| |
| uint32_t previous_major; |
| if (!base::StringToUint(version_components[MAJOR], &previous_major)) |
| previous_major = 0; |
| |
| // Unconditionally update the major version. |
| version_components[MAJOR] = kActiveSetupMajorVersion; |
| |
| // Clear the other components if the major version increased. No extra work is |
| // needed for UPDATE_AND_BUMP_SELECTIVE_TRIGGER in this case since all |
| // users will re-run active setup. |
| if (ACTIVE_SETUP_MAJOR_VERSION > previous_major) { |
| std::fill_n(++version_components.begin(), 3, base::string16(L"0")); |
| } else if (operation_ == UPDATE_AND_BUMP_SELECTIVE_TRIGGER) { |
| uint32_t previous_value; |
| if (!base::StringToUint(version_components[SELECTIVE_TRIGGER], |
| &previous_value)) { |
| LOG(WARNING) << "Couldn't process previous SELECTIVE_TRIGGER Active " |
| "Setup version component: " |
| << version_components[SELECTIVE_TRIGGER]; |
| previous_value = 0; |
| } |
| version_components[SELECTIVE_TRIGGER] = |
| base::UintToString16(previous_value + 1); |
| } |
| |
| return base::JoinString(version_components, L","); |
| } |