winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

UserSettings.h (13599B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #pragma once
      4 #include "AppInstallerStrings.h"
      5 #include "AppInstallerLogging.h"
      6 #include "winget/Archive.h"
      7 #include "winget/GroupPolicy.h"
      8 #include "winget/Resources.h"
      9 #include "winget/ManifestCommon.h"
     10 
     11 #include <filesystem>
     12 #include <map>
     13 #include <optional>
     14 #include <string>
     15 #include <type_traits>
     16 #include <variant>
     17 #include <vector>
     18 
     19 #include "AppInstallerArchitecture.h"
     20 
     21 using namespace std::chrono_literals;
     22 using namespace std::string_view_literals;
     23 
     24 namespace AppInstaller::Settings
     25 {
     26     // The type of argument.
     27     enum class UserSettingsType
     28     {
     29         // Settings files don't exist. A file is created on the first call to the settings command.
     30         Default,
     31         // Loaded settings.json
     32         Standard,
     33         // Loaded settings.json.backup
     34         Backup,
     35         // Loaded from custom settings content
     36         Custom,
     37     };
     38 
     39     // The visual style of the progress bar.
     40     enum class VisualStyle
     41     {
     42         NoVT,
     43         Retro,
     44         Accent,
     45         Rainbow,
     46         Sixel,
     47         Disabled,
     48     };
     49 
     50     // The download code to use for *installers*.
     51     enum class InstallerDownloader
     52     {
     53         Default,
     54         WinInet,
     55         DeliveryOptimization,
     56     };
     57 
     58     // Enum of settings.
     59     // Must start at 0 to enable direct access to variant in UserSettings.
     60     // Max must be last and unused.
     61     // How to add a setting
     62     // 1 - Add to enum.
     63     // 2 - Implement SettingMap specialization via SETTINGMAPPING_SPECIALIZATION
     64     // Validate will be called by ValidateAll without any more changes.
     65     enum class Setting : size_t
     66     {
     67         // Visual
     68         ProgressBarVisualStyle,
     69         AnonymizePathForDisplay,
     70         EnableSixelDisplay,
     71         // Source
     72         AutoUpdateTimeInMinutes,
     73         // Experimental
     74         EFExperimentalCmd,
     75         EFExperimentalArg,
     76         EFDirectMSI,
     77         EFResume,
     78         EFFonts,
     79         // Telemetry
     80         TelemetryDisable,
     81         // Install behavior
     82         InstallScopePreference,
     83         InstallScopeRequirement,
     84         InstallArchitecturePreference,
     85         InstallArchitectureRequirement,
     86         InstallLocalePreference,
     87         InstallLocaleRequirement,
     88         InstallerTypePreference,
     89         InstallerTypeRequirement,
     90         InstallDefaultRoot,
     91         InstallSkipDependencies,
     92         ArchiveExtractionMethod,
     93         DisableInstallNotes,
     94         PortablePackageUserRoot,
     95         PortablePackageMachineRoot,
     96         MaxResumes,
     97         // Network
     98         NetworkDownloader,
     99         NetworkDOProgressTimeoutInSeconds,
    100         NetworkWingetAlternateSourceURL,
    101         // Logging
    102         LoggingLevelPreference,
    103         LoggingChannelPreference,
    104         // Uninstall behavior
    105         UninstallPurgePortablePackage,
    106         // Download behavior
    107         DownloadDefaultDirectory,
    108         // Configure behavior
    109         ConfigureDefaultModuleRoot,
    110         // Interactivity
    111         InteractivityDisable,
    112 #ifndef AICLI_DISABLE_TEST_HOOKS
    113         // Debug
    114         EnableSelfInitiatedMinidump,
    115         KeepAllLogFiles,
    116 #endif
    117         Max
    118     };
    119 
    120     namespace details
    121     {
    122         template <Setting S>
    123         struct SettingMapping
    124         {
    125             // json_t - type the setting in json.
    126             // value_t - the type of this setting.
    127             // DefaultValue - the value_t default value when setting is absent or semantically wrong.
    128             // Path - json path to the property. See Json::Path in json.h for syntax. So far, this is sufficient
    129             //        but since is "brief" and "untested" we might implement our own if needed.
    130             // Validate - Function that does semantic validation.
    131         };
    132 
    133 #define SETTINGMAPPING_SPECIALIZATION_POLICY(_setting_, _json_, _value_, _default_, _path_, _valuePolicy_) \
    134         template <> \
    135         struct SettingMapping<_setting_> \
    136         { \
    137             using json_t = _json_; \
    138             using value_t = _value_; \
    139             inline static const value_t DefaultValue = _default_; \
    140             static constexpr std::string_view Path = _path_; \
    141             static std::optional<value_t> Validate(const json_t& value); \
    142             static constexpr ValuePolicy Policy = _valuePolicy_; \
    143             using policy_t = GroupPolicy::ValueType<Policy>; \
    144             static_assert(Policy == ValuePolicy::None || std::is_same<json_t, policy_t>::value); \
    145         }
    146 
    147 #define SETTINGMAPPING_SPECIALIZATION(_setting_, _json_, _value_, _default_, _path_) \
    148         SETTINGMAPPING_SPECIALIZATION_POLICY(_setting_, _json_, _value_, _default_, _path_, ValuePolicy::None)
    149 
    150         // Visual
    151         SETTINGMAPPING_SPECIALIZATION(Setting::ProgressBarVisualStyle, std::string, VisualStyle, VisualStyle::Accent, ".visual.progressBar"sv);
    152         SETTINGMAPPING_SPECIALIZATION(Setting::AnonymizePathForDisplay, bool, bool, true, ".visual.anonymizeDisplayedPaths"sv);
    153         SETTINGMAPPING_SPECIALIZATION(Setting::EnableSixelDisplay, bool, bool, false, ".visual.enableSixels"sv);
    154         // Source
    155         SETTINGMAPPING_SPECIALIZATION_POLICY(Setting::AutoUpdateTimeInMinutes, uint32_t, std::chrono::minutes, 15min, ".source.autoUpdateIntervalInMinutes"sv, ValuePolicy::SourceAutoUpdateIntervalInMinutes);
    156         // Experimental
    157         SETTINGMAPPING_SPECIALIZATION(Setting::EFExperimentalCmd, bool, bool, false, ".experimentalFeatures.experimentalCmd"sv);
    158         SETTINGMAPPING_SPECIALIZATION(Setting::EFExperimentalArg, bool, bool, false, ".experimentalFeatures.experimentalArg"sv);
    159         SETTINGMAPPING_SPECIALIZATION(Setting::EFDirectMSI, bool, bool, false, ".experimentalFeatures.directMSI"sv);
    160         SETTINGMAPPING_SPECIALIZATION(Setting::EFResume, bool, bool, false, ".experimentalFeatures.resume"sv);
    161         SETTINGMAPPING_SPECIALIZATION(Setting::EFFonts, bool, bool, false, ".experimentalFeatures.fonts"sv);
    162         // Telemetry
    163         SETTINGMAPPING_SPECIALIZATION(Setting::TelemetryDisable, bool, bool, false, ".telemetry.disable"sv);
    164         // Install behavior
    165         SETTINGMAPPING_SPECIALIZATION(Setting::InstallArchitecturePreference, std::vector<std::string>, std::vector<Utility::Architecture>, {}, ".installBehavior.preferences.architectures"sv);
    166         SETTINGMAPPING_SPECIALIZATION(Setting::InstallArchitectureRequirement, std::vector<std::string>, std::vector<Utility::Architecture>, {}, ".installBehavior.requirements.architectures"sv);
    167         SETTINGMAPPING_SPECIALIZATION(Setting::InstallScopePreference, std::string, Manifest::ScopeEnum, Manifest::ScopeEnum::User, ".installBehavior.preferences.scope"sv);
    168         SETTINGMAPPING_SPECIALIZATION(Setting::InstallScopeRequirement, std::string, Manifest::ScopeEnum, Manifest::ScopeEnum::Unknown, ".installBehavior.requirements.scope"sv);
    169         SETTINGMAPPING_SPECIALIZATION(Setting::InstallLocalePreference, std::vector<std::string>, std::vector<std::string>, {}, ".installBehavior.preferences.locale"sv);
    170         SETTINGMAPPING_SPECIALIZATION(Setting::InstallLocaleRequirement, std::vector<std::string>, std::vector<std::string>, {}, ".installBehavior.requirements.locale"sv);
    171         SETTINGMAPPING_SPECIALIZATION(Setting::InstallerTypePreference, std::vector<std::string>, std::vector<Manifest::InstallerTypeEnum>, {}, ".installBehavior.preferences.installerTypes"sv);
    172         SETTINGMAPPING_SPECIALIZATION(Setting::InstallerTypeRequirement, std::vector<std::string>, std::vector<Manifest::InstallerTypeEnum>, {}, ".installBehavior.requirements.installerTypes"sv);
    173         SETTINGMAPPING_SPECIALIZATION(Setting::InstallSkipDependencies, bool, bool, false, ".installBehavior.skipDependencies"sv);
    174         SETTINGMAPPING_SPECIALIZATION(Setting::ArchiveExtractionMethod, std::string, Archive::ExtractionMethod, Archive::ExtractionMethod::ShellApi, ".installBehavior.archiveExtractionMethod"sv);
    175         SETTINGMAPPING_SPECIALIZATION(Setting::DisableInstallNotes, bool, bool, false, ".installBehavior.disableInstallNotes"sv);
    176         SETTINGMAPPING_SPECIALIZATION(Setting::PortablePackageUserRoot, std::string, std::filesystem::path, {}, ".installBehavior.portablePackageUserRoot"sv);
    177         SETTINGMAPPING_SPECIALIZATION(Setting::PortablePackageMachineRoot, std::string, std::filesystem::path, {}, ".installBehavior.portablePackageMachineRoot"sv);
    178         SETTINGMAPPING_SPECIALIZATION(Setting::InstallDefaultRoot, std::string, std::filesystem::path, {}, ".installBehavior.defaultInstallRoot"sv);
    179         SETTINGMAPPING_SPECIALIZATION(Setting::MaxResumes, uint32_t, int, 3, ".installBehavior.maxResumes"sv);
    180         // Uninstall behavior
    181         SETTINGMAPPING_SPECIALIZATION(Setting::UninstallPurgePortablePackage, bool, bool, false, ".uninstallBehavior.purgePortablePackage"sv);
    182         // Download behavior
    183         SETTINGMAPPING_SPECIALIZATION(Setting::DownloadDefaultDirectory, std::string, std::filesystem::path, {}, ".downloadBehavior.defaultDownloadDirectory"sv);
    184         // Configure behavior
    185         SETTINGMAPPING_SPECIALIZATION(Setting::ConfigureDefaultModuleRoot, std::string, std::filesystem::path, {}, ".configureBehavior.defaultModuleRoot"sv);
    186 
    187         // Network
    188         SETTINGMAPPING_SPECIALIZATION(Setting::NetworkDownloader, std::string, InstallerDownloader, InstallerDownloader::Default, ".network.downloader"sv);
    189         SETTINGMAPPING_SPECIALIZATION(Setting::NetworkDOProgressTimeoutInSeconds, uint32_t, std::chrono::seconds, 60s, ".network.doProgressTimeoutInSeconds"sv);
    190         SETTINGMAPPING_SPECIALIZATION(Setting::NetworkWingetAlternateSourceURL, bool, bool, true, ".network.enableWingetAlternateSourceURL"sv);
    191 #ifndef AICLI_DISABLE_TEST_HOOKS
    192         // Debug
    193         SETTINGMAPPING_SPECIALIZATION(Setting::EnableSelfInitiatedMinidump, bool, bool, false, ".debugging.enableSelfInitiatedMinidump"sv);
    194         SETTINGMAPPING_SPECIALIZATION(Setting::KeepAllLogFiles, bool, bool, false, ".debugging.keepAllLogFiles"sv);
    195 #endif
    196         // Logging
    197         SETTINGMAPPING_SPECIALIZATION(Setting::LoggingLevelPreference, std::string, Logging::Level, Logging::Level::Info, ".logging.level"sv);
    198         SETTINGMAPPING_SPECIALIZATION(Setting::LoggingChannelPreference, std::vector<std::string>, Logging::Channel, Logging::Channel::Defaults, ".logging.channels"sv);
    199         // Interactivity
    200         SETTINGMAPPING_SPECIALIZATION(Setting::InteractivityDisable, bool, bool, false, ".interactivity.disable"sv);
    201         
    202         // Used to deduce the SettingVariant type; making a variant that includes std::monostate and all SettingMapping types.
    203         template <size_t... I>
    204         inline auto Deduce(std::index_sequence<I...>) { return std::variant<std::monostate, typename SettingMapping<static_cast<Setting>(I)>::value_t...>{}; }
    205 
    206         // Holds data of any type listed in a SettingMapping.
    207         using SettingVariant = decltype(Deduce(std::make_index_sequence<static_cast<size_t>(Setting::Max)>()));
    208 
    209         // Gets the index into the variant for the given Setting.
    210         constexpr inline size_t SettingIndex(Setting s) { return static_cast<size_t>(s) + 1; }
    211     }
    212 
    213     // Representation of the parsed settings file.
    214     struct UserSettings
    215     {
    216         // Jsoncpp doesn't provide line number and column for an individual Json::Value node.
    217         struct Warning
    218         {
    219             Warning(StringResource::StringId message) : Message(message) {}
    220             Warning(StringResource::StringId message, std::string_view settingPath) : Message(message), Path(settingPath) {}
    221             Warning(StringResource::StringId message, std::string_view settingPath, std::string_view settingValue, bool isField = true) :
    222                 Message(message), Path(settingPath), Data(settingValue), IsFieldWarning(isField) {}
    223 
    224             StringResource::StringId Message;
    225             Utility::LocIndString Path;
    226             Utility::LocIndString Data;
    227             bool IsFieldWarning = true;
    228         };
    229 
    230         static UserSettings const& Instance(const std::optional<std::string>& content = std::nullopt);
    231 
    232         static std::filesystem::path SettingsFilePath(bool forDisplay = false);
    233 
    234         UserSettings(const UserSettings&) = delete;
    235         UserSettings& operator=(const UserSettings&) = delete;
    236 
    237         UserSettings(UserSettings&&) = delete;
    238         UserSettings& operator=(UserSettings&&) = delete;
    239 
    240         UserSettingsType GetType() const { return m_type; }
    241         std::vector<Warning> const& GetWarnings() const { return m_warnings; }
    242 
    243         void PrepareToShellExecuteFile() const;
    244 
    245         // Gets setting value, if its not in the map it returns the default value.
    246         template <Setting S>
    247         typename details::SettingMapping<S>::value_t Get() const
    248         {
    249             auto itr = m_settings.find(S);
    250             if (itr == m_settings.end())
    251             {
    252                 return details::SettingMapping<S>::DefaultValue;
    253             }
    254 
    255             return std::get<details::SettingIndex(S)>(itr->second);
    256         }
    257 
    258     protected:
    259         UserSettingsType m_type = UserSettingsType::Default;
    260         std::vector<Warning> m_warnings;
    261         std::map<Setting, details::SettingVariant> m_settings;
    262 
    263         UserSettings(const std::optional<std::string>& content = std::nullopt);
    264         ~UserSettings() = default;
    265     };
    266 
    267     const UserSettings* TryGetUser();
    268     UserSettings const& User();
    269     bool TryInitializeCustomUserSettings(std::string content);
    270 }